Doxygen Book
nnstreamer_plugin_api_impl.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-only */
16 #include <nnstreamer_util.h>
17 #include <string.h>
18 #include <tensor_common.h>
19 
20 static const gchar *gst_tensor_time_sync_mode_string[] = {
21  [SYNC_NOSYNC] = "nosync",
22  [SYNC_SLOWEST] = "slowest",
23  [SYNC_BASEPAD] = "basepad",
24  [SYNC_REFRESH] = "refresh",
25  [SYNC_END] = NULL
26 };
27 
31 #define NNS_TENSOR_RANK_LIMIT_PREV (4)
32 
33 #define NNS_TENSOR_EXTRA_MAGIC 0xf00dc0de
34 
39 typedef struct
40 {
41  uint32_t magic;
42  uint32_t version;
44  uint64_t reserved;
47 
53 static gboolean
55 {
56  GstTensorExtraInfo *extra_info;
57  gboolean is_extra;
58 
59  g_return_val_if_fail (map != NULL, FALSE);
60 
61  if (map->size < sizeof (GstTensorExtraInfo))
62  return FALSE;
63 
64  extra_info = (GstTensorExtraInfo *) map->data;
65 
66  /* check magic in header (extra info) of the memory */
67  is_extra = (extra_info && extra_info->magic == NNS_TENSOR_EXTRA_MAGIC);
68 
69  return is_extra;
70 }
71 
77 static void
78 gst_tensor_extra_info_init (GstTensorExtraInfo * extra, gsize reserved_size)
79 {
80  guint i;
81 
82  g_return_if_fail (extra != NULL);
83 
85  extra->version = 0;
86  extra->num_extra_tensors = 0;
87 
88  /* set reserved size of NNS_TENSOR_SIZE_LIMIT-th memory */
89  extra->reserved = reserved_size;
90  for (i = 0; i < NNS_TENSOR_SIZE_EXTRA_LIMIT; ++i) {
91  gst_tensor_info_init (&extra->infos[i]);
92  }
93 }
94 
101 gst_tensor_time_sync_get_mode (const gchar * str)
102 {
103  gint index;
104 
106 
107  return (index < 0) ? SYNC_END : index;
108 }
109 
114 const gchar *
116 {
118 }
119 
125 gboolean
127 {
128  g_return_val_if_fail (sync != NULL, FALSE);
129 
130  if (sync->mode == SYNC_END || sync->option == NULL)
131  return FALSE;
132 
133  switch (sync->mode) {
134  case SYNC_NOSYNC:
135  break;
136  case SYNC_SLOWEST:
137  break;
138  case SYNC_BASEPAD:
139  {
140  g_auto (GStrv) strv = g_strsplit (sync->option, ":", 2);
141  guint sink_id;
142  guint duration;
143 
144  if (strv[0] != NULL)
145  sink_id = (guint) g_ascii_strtoull (strv[0], NULL, 10);
146  else
147  sink_id = 0;
148 
149  if (strv[1] != NULL)
150  duration = (guint) g_ascii_strtoull (strv[1], NULL, 10);
151  else
152  duration = G_MAXINT;
153 
154  sync->data_basepad.sink_id = sink_id;
155  sync->data_basepad.duration = duration;
156  break;
157  }
158  default:
159  /* unknown mode */
160  GST_WARNING ("Unknown mode = %d", sync->mode);
161  return FALSE;
162  }
163 
164  return TRUE;
165 }
166 
174 static gboolean
175 _gst_tensor_time_sync_is_eos (GstCollectPads * collect,
176  tensor_time_sync_data * sync, guint empty)
177 {
178  guint total;
179  gboolean is_eos = FALSE;
180 
181  total = g_slist_length (collect->data);
182 
183  switch (sync->mode) {
184  case SYNC_REFRESH:
185  if (empty == total)
186  is_eos = TRUE;
187  break;
188  default:
189  if (empty > 0)
190  is_eos = TRUE;
191  break;
192  }
193 
194  return is_eos;
195 }
196 
202 gboolean
203 gst_tensor_time_sync_get_current_time (GstCollectPads * collect,
204  tensor_time_sync_data * sync, GstClockTime * current_time,
205  GstBuffer * tensors_buf)
206 {
207  GSList *walk = NULL;
208  guint count, empty_pad;
209 
210  g_return_val_if_fail (collect != NULL, FALSE);
211  g_return_val_if_fail (sync != NULL, FALSE);
212  g_return_val_if_fail (current_time != NULL, FALSE);
213 
214  walk = collect->data;
215  count = empty_pad = 0;
216 
217  while (walk) {
218  GstCollectData *data;
219  GstBuffer *buf;
220  gboolean need_update = FALSE;
221 
222  data = (GstCollectData *) walk->data;
223  buf = gst_collect_pads_peek (collect, data);
224  walk = g_slist_next (walk);
225 
226  if (buf) {
227  switch (sync->mode) {
228  case SYNC_NOSYNC:
229  /* fall-through */
230  case SYNC_SLOWEST:
231  case SYNC_REFRESH:
232  if (*current_time < GST_BUFFER_PTS (buf))
233  need_update = TRUE;
234  break;
235  case SYNC_BASEPAD:
236  if (count == sync->data_basepad.sink_id)
237  need_update = TRUE;
238  break;
239  default:
240  break;
241  }
242  if (need_update) {
243  *current_time = GST_BUFFER_PTS (buf);
244  gst_buffer_copy_into (tensors_buf, buf, GST_BUFFER_COPY_METADATA,
245  0, -1);
246  }
247  gst_buffer_unref (buf);
248  } else {
249  empty_pad++;
250  }
251 
252  count++;
253  }
254 
255  return _gst_tensor_time_sync_is_eos (collect, sync, empty_pad);
256 }
257 
262 void
263 gst_tensor_time_sync_flush (GstCollectPads * collect)
264 {
265  GSList *walk;
267 
268  g_return_if_fail (collect != NULL);
269 
270  walk = collect->data;
271  while (walk) {
272  pad = (GstTensorCollectPadData *) walk->data;
273 
274  if (pad->buffer) {
275  gst_buffer_unref (pad->buffer);
276  pad->buffer = NULL;
277  }
278 
279  walk = g_slist_next (walk);
280  }
281 }
282 
286 static gboolean
287 _gst_tensor_time_sync_buffer_update (GstCollectPads * collect,
288  GstCollectData * data, GstClockTime current, GstClockTime base,
289  tensor_time_sync_data * sync)
290 {
292  GstBuffer *buf;
293 
294  pad = (GstTensorCollectPadData *) data;
295 
296  buf = gst_collect_pads_peek (collect, data);
297  if (buf != NULL) {
298  if (GST_BUFFER_PTS (buf) < current) {
299  gst_buffer_unref (buf);
300  if (pad->buffer != NULL)
301  gst_buffer_unref (pad->buffer);
302  pad->buffer = gst_collect_pads_pop (collect, data);
303  return FALSE;
304  }
305 
306  if ((sync->mode == SYNC_SLOWEST && pad->buffer != NULL &&
307  (ABS (GST_CLOCK_DIFF (current, GST_BUFFER_PTS (pad->buffer))) <
308  ABS (GST_CLOCK_DIFF (current, GST_BUFFER_PTS (buf))))) ||
309  (sync->mode == SYNC_BASEPAD && pad->buffer != NULL &&
310  (((GstClockTime) ABS (GST_CLOCK_DIFF (current,
311  GST_BUFFER_PTS (buf)))) > base))) {
312  /* keep last buffer */
313  } else {
314  /* update last buffer */
315  if (pad->buffer != NULL)
316  gst_buffer_unref (pad->buffer);
317  pad->buffer = gst_collect_pads_pop (collect, data);
318  }
319 
320  gst_buffer_unref (buf);
321  }
322 
323  return TRUE;
324 }
325 
331 gboolean
333  tensor_time_sync_data * sync, GstClockTime current_time,
334  GstBuffer * tensors_buf, GstTensorsConfig * configs, gboolean * is_eos)
335 {
336  GSList *walk = NULL;
337  GstCollectData *data;
339  GstBuffer *buf = NULL;
340  GstMemory *mem;
341  gint old_numerator = G_MAXINT;
342  gint old_denominator = G_MAXINT;
343  guint counting, empty_pad;
344  GstTensorsConfig in_configs;
345  GstClockTime base_time = 0;
346  GstTensorInfo *_info;
347  guint i, j;
348  GstMemory *in_mem[NNS_TENSOR_SIZE_LIMIT];
350 
351  g_return_val_if_fail (collect != NULL, FALSE);
352  g_return_val_if_fail (sync != NULL, FALSE);
353  g_return_val_if_fail (tensors_buf != NULL, FALSE);
354  g_return_val_if_fail (configs != NULL, FALSE);
355  g_return_val_if_fail (is_eos != NULL, FALSE);
356 
357  walk = collect->data;
358  counting = empty_pad = 0;
359 
360  if (sync->mode == SYNC_BASEPAD) {
361  walk = g_slist_nth (walk, sync->data_basepad.sink_id);
362  if (walk == NULL) {
363  GST_ERROR_OBJECT (collect, "Cannot get GstCollectData from GSList");
364  return FALSE;
365  }
366 
367  data = (GstCollectData *) walk->data;
368  pad = (GstTensorCollectPadData *) data;
369 
370  buf = gst_collect_pads_peek (collect, data);
371  if (buf != NULL) {
372  if (pad->buffer != NULL)
373  base_time =
374  MIN ((GstClockTimeDiff) sync->data_basepad.duration,
375  ABS (GST_CLOCK_DIFF (GST_BUFFER_PTS (buf),
376  GST_BUFFER_PTS (pad->buffer))) - 1);
377  gst_buffer_unref (buf);
378  }
379  }
380 
381  walk = collect->data;
382 
383  gst_tensors_config_init (&in_configs);
384 
385  while (walk) {
386  gboolean configured = FALSE;
387  gboolean is_empty = FALSE;
388 
389  data = (GstCollectData *) walk->data;
390  pad = (GstTensorCollectPadData *) data;
391 
392  if (gst_pad_has_current_caps (data->pad)) {
393  GstCaps *caps = gst_pad_get_current_caps (data->pad);
394  GstStructure *s = gst_caps_get_structure (caps, 0);
395 
396  if (gst_tensors_config_validate (&in_configs))
397  gst_tensors_config_free (&in_configs);
398 
399  gst_tensors_config_from_structure (&in_configs, s);
400  gst_caps_unref (caps);
401 
402  configured = gst_tensors_config_validate (&in_configs);
403  }
404 
412  if (!configured) {
413  return FALSE;
414  }
415 
416  if (in_configs.rate_d < old_denominator)
417  old_denominator = in_configs.rate_d;
418  if (in_configs.rate_n < old_numerator)
419  old_numerator = in_configs.rate_n;
420 
421  walk = g_slist_next (walk);
422 
423  switch (sync->mode) {
424  case SYNC_SLOWEST:
425  /* fall-through */
426  case SYNC_BASEPAD:
428  current_time, base_time, sync))
429  return FALSE;
430  buf = gst_buffer_ref (pad->buffer);
431  is_empty = (buf == NULL);
432  break;
433  case SYNC_NOSYNC:
434  buf = gst_collect_pads_pop (collect, data);
435  is_empty = (buf == NULL);
436  break;
437  case SYNC_REFRESH:
438  buf = gst_collect_pads_pop (collect, data);
439  if (buf != NULL) {
440  if (pad->buffer != NULL) {
441  gst_buffer_unref (pad->buffer);
442  }
443  pad->buffer = gst_buffer_ref (buf);
444  } else {
445  if (pad->buffer == NULL) {
446  *is_eos = FALSE;
447  ml_logd ("Not the all buffers are arrived yet.");
448  return FALSE;
449  }
450  is_empty = TRUE;
451  buf = gst_buffer_ref (pad->buffer);
452  }
453  break;
454  default:
455  break;
456  }
457 
458  if (GST_IS_BUFFER (buf)) {
459  guint32 n_tensor = gst_tensor_buffer_get_count (buf);
460  buf = gst_tensor_buffer_from_config (buf, &in_configs);
461 
464  if (gst_tensors_config_is_static (&in_configs))
465  g_assert (n_tensor == in_configs.info.num_tensors);
466  g_assert ((counting + n_tensor) <= NNS_TENSOR_SIZE_LIMIT);
467 
468  if (gst_tensors_config_is_flexible (&in_configs))
470 
471  for (i = 0; i < n_tensor; ++i) {
472  in_mem[counting] = gst_tensor_buffer_get_nth_memory (buf, i);
473 
474  /* set info */
476  counting), gst_tensors_info_get_nth_info (&in_configs.info, i));
477  in_formats[counting] = in_configs.info.format;
478  counting++;
479  }
480 
481  gst_buffer_unref (buf);
482  }
483  if (is_empty)
484  empty_pad++;
485  }
486 
487  /* append memories to output buffer */
488  for (i = 0; i < counting; i++) {
489  _info = gst_tensors_info_get_nth_info (&configs->info, i);
490  mem = in_mem[i];
491 
492  if (gst_tensors_config_is_flexible (configs)) {
493  /* append header if input tensor is not flexible */
494  if (in_formats[i] != _NNS_TENSOR_FORMAT_FLEXIBLE) {
495  GstTensorMetaInfo meta;
496 
497  gst_tensor_info_convert_to_meta (_info, &meta);
498  mem = gst_tensor_meta_info_append_header (&meta, in_mem[i]);
499  gst_memory_unref (in_mem[i]);
500  }
501  }
502 
503  if (!gst_tensor_buffer_append_memory (tensors_buf, mem, _info)) {
504  for (j = i + 1; j < counting; j++)
505  gst_memory_unref (in_mem[j]);
506 
507  nns_loge ("Failed to append memory to buffer.");
508  return FALSE;
509  }
510  }
511 
512  configs->info.num_tensors = counting;
513  configs->rate_d = old_denominator;
514  configs->rate_n = old_numerator;
515 
516  GST_BUFFER_PTS (tensors_buf) = current_time;
517 
518  gst_tensors_config_free (&in_configs);
519 
520  /* check eos */
521  *is_eos = _gst_tensor_time_sync_is_eos (collect, sync, empty_pad);
522  return !(*is_eos);
523 }
524 
534 GstBuffer *
536 {
537  GstBuffer *out = NULL;
538  GstMemory *all = NULL;
539  GstMapInfo map;
540  guint i, num;
541  gsize total, offset;
542  gsize mem_size[NNS_TENSOR_MEMORY_MAX];
543  gboolean configured = FALSE;
544  gboolean is_extra = FALSE;
545 
546  if (!GST_IS_BUFFER (in)) {
547  nns_loge ("Failed to get tensor buffer, invalid input buffer.");
548  return NULL;
549  }
550 
551  if (!gst_tensors_config_validate (config)) {
552  nns_loge ("Failed to get tensor buffer, invalid tensor configuration.");
553  goto error;
554  }
555 
556  num = gst_buffer_n_memory (in);
557  total = gst_buffer_get_size (in);
558 
559  /* get memory size */
560  if (gst_tensors_config_is_static (config)) {
561  if (num == config->info.num_tensors) {
562  /* Do nothing, pass input buffer. */
563  out = gst_buffer_ref (in);
564  goto done;
565  }
566 
567  num = config->info.num_tensors;
568  if ((is_extra = (num > NNS_TENSOR_MEMORY_MAX)))
569  num = NNS_TENSOR_MEMORY_MAX;
570  for (i = 0; i < num; i++)
571  mem_size[i] = gst_tensors_info_get_size (&config->info, i);
572  if (is_extra) {
573  mem_size[num - 1] += sizeof (GstTensorExtraInfo);
574  for (; i < config->info.num_tensors; i++)
575  mem_size[num - 1] += gst_tensors_info_get_size (&config->info, i);
576  }
577  } else {
578  if (num > 1) {
579  /* Suppose it is already configured. */
580  out = gst_buffer_ref (in);
581  goto done;
582  }
583 
584  if (!gst_buffer_map (in, &map, GST_MAP_READ)) {
585  nns_loge ("Failed to get tensor buffer, cannot get the memory info.");
586  goto error;
587  }
588 
589  num = 0;
590  offset = 0;
591  while (offset < total) {
592  GstTensorMetaInfo meta;
593  gpointer h = map.data + offset;
594 
595  if (num >= NNS_TENSOR_MEMORY_MAX - 1) {
596  /* Suppose remained memory may include extra tensors. */
597  mem_size[num++] = total - offset;
598  break;
599  }
600 
602  mem_size[num] = gst_tensor_meta_info_get_header_size (&meta);
603  mem_size[num] += gst_tensor_meta_info_get_data_size (&meta);
604 
605  offset += mem_size[num];
606  num++;
607  }
608 
609  gst_buffer_unmap (in, &map);
610 
611  if (num == 1) {
612  /* Do nothing, pass input buffer. */
613  out = gst_buffer_ref (in);
614  goto done;
615  }
616  }
617 
618  /* configure output buffer */
619  out = gst_buffer_new ();
620  all = gst_buffer_get_all_memory (in);
621  offset = 0;
622 
623  for (i = 0; i < num; i++) {
624  /* invalid memory size */
625  if (offset + mem_size[i] > total) {
626  nns_loge ("Failed to get tensor buffer, data size is mismatched.");
627  goto error;
628  }
629 
630  gst_buffer_append_memory (out, gst_memory_share (all, offset, mem_size[i]));
631  offset += mem_size[i];
632  }
633 
634  gst_buffer_copy_into (out, in, GST_BUFFER_COPY_METADATA, 0, -1);
635 
636 done:
637  configured = TRUE;
638 error:
639  gst_buffer_unref (in);
640 
641  if (all)
642  gst_memory_unref (all);
643 
644  if (!configured) {
645  if (out) {
646  gst_buffer_unref (out);
647  out = NULL;
648  }
649  }
650 
651  return out;
652 }
653 
657 typedef struct
658 {
659  GstAdapter *adapter;
661 
662 #define AGGREGATION_DEFAULT_KEY 0xC0FFEEU
663 
667 static void
669 {
671 
673  if (aggr) {
674  gst_adapter_clear (aggr->adapter);
675  g_object_unref (aggr->adapter);
676 
677  g_free (aggr);
678  }
679 }
680 
685 gst_tensor_aggregation_add_data (GHashTable * table, const guint32 key)
686 {
688  guint32 hashkey;
689 
690  g_return_val_if_fail (table != NULL, NULL);
691  if (key == 0)
692  hashkey = AGGREGATION_DEFAULT_KEY;
693  else
694  hashkey = key;
695  aggr = g_new0 (gst_tensor_aggregation_data_s, 1);
696  aggr->adapter = gst_adapter_new ();
697 
698  g_hash_table_insert (table, GINT_TO_POINTER (hashkey), aggr);
699  return aggr;
700 }
701 
706 gst_tensor_aggregation_get_data (GHashTable * table, const guint32 key)
707 {
708  g_return_val_if_fail (table != NULL, NULL);
709 
710  return (gst_tensor_aggregation_data_s *) g_hash_table_lookup (table,
711  GINT_TO_POINTER (key == 0 ? AGGREGATION_DEFAULT_KEY : key));
712 }
713 
717 static void
718 gst_tensor_aggregation_clear_internal (gpointer key, gpointer value,
719  gpointer user_data)
720 {
722 
723  UNUSED (key);
724  UNUSED (user_data);
725 
726  aggr = (gst_tensor_aggregation_data_s *) value;
727  if (aggr) {
728  gst_adapter_clear (aggr->adapter);
729  }
730 }
731 
736 GHashTable *
738 {
739  GHashTable *table;
740 
741  table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
743 
753 
754  return table;
755 }
756 
762 void
763 gst_tensor_aggregation_clear (GHashTable * table, const guint32 key)
764 {
766 
767  g_return_if_fail (table != NULL);
768 
769  aggr = gst_tensor_aggregation_get_data (table, key);
770  gst_tensor_aggregation_clear_internal (NULL, aggr, NULL);
771 }
772 
777 void
779 {
780  g_hash_table_foreach (table, gst_tensor_aggregation_clear_internal, NULL);
781 }
782 
789 GstAdapter *
790 gst_tensor_aggregation_get_adapter (GHashTable * table, const guint32 key)
791 {
793 
794  g_return_val_if_fail (table != NULL, NULL);
795 
796  aggr = gst_tensor_aggregation_get_data (table, key);
797  if (!aggr) {
798  /*append new data */
799  aggr = gst_tensor_aggregation_add_data (table, key);
800  }
801 
802  return aggr->adapter;
803 }
804 
808 static gboolean
810 {
811  GstTensorsInfo *info;
812  GstTensorInfo *_info;
813  guint i, rank, min_rank;
814 
815  g_return_val_if_fail (config != NULL, FALSE);
816 
817  info = (GstTensorsInfo *) (&config->info);
818  if (!gst_tensors_info_validate (info))
819  return FALSE;
820 
821  for (i = 0; i < info->num_tensors; i++) {
822  _info = gst_tensors_info_get_nth_info (info, i);
823 
825  min_rank = gst_tensor_dimension_get_min_rank (_info->dimension);
826 
827  if (rank <= NNS_TENSOR_RANK_LIMIT_PREV ||
828  min_rank > NNS_TENSOR_RANK_LIMIT_PREV)
829  return FALSE;
830  }
831 
832  return TRUE;
833 }
834 
838 static GstCaps *
840 {
841  GstCaps *caps;
842  GstStructure *structure = NULL;
843  GstTensorsInfo *info;
844  GstTensorInfo *_info;
845 
846  g_return_val_if_fail (config != NULL, NULL);
847 
848  info = (GstTensorsInfo *) (&config->info);
849  if (info->num_tensors > 1)
850  return NULL;
851 
852  caps = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT);
853  _info = gst_tensors_info_get_nth_info (info, 0);
854 
855  /* structure for backward compatibility */
856  if (_append_prev_caps (config))
857  structure = gst_structure_new_empty (NNS_MIMETYPE_TENSOR);
858 
860  {
861  g_autofree gchar *dim_str =
863 
864  gst_caps_set_simple (caps, "dimension", G_TYPE_STRING, dim_str, NULL);
865  }
866 
867  if (structure) {
868  g_autofree gchar *dim_str =
871 
872  gst_structure_set (structure, "dimension", G_TYPE_STRING, dim_str, NULL);
873  }
874  }
875 
876  if (_info->type != _NNS_END) {
877  const gchar *type_str = gst_tensor_get_type_string (_info->type);
878 
879  gst_caps_set_simple (caps, "type", G_TYPE_STRING, type_str, NULL);
880 
881  if (structure)
882  gst_structure_set (structure, "type", G_TYPE_STRING, type_str, NULL);
883  }
884 
885  if (config->rate_n >= 0 && config->rate_d > 0) {
886  gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
887  config->rate_n, config->rate_d, NULL);
888 
889  if (structure)
890  gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
891  config->rate_n, config->rate_d, NULL);
892  }
893 
894  if (structure)
895  gst_caps_append_structure (caps, structure);
896 
897  return caps;
898 }
899 
903 static GstCaps *
905 {
906  GstCaps *caps;
907  GstStructure *structure = NULL;
908 
909  g_return_val_if_fail (config != NULL, NULL);
910 
911  caps = gst_caps_from_string (GST_TENSORS_CAP_DEFAULT);
912 
913  /* structure for backward compatibility */
914  if (_append_prev_caps (config))
915  structure = gst_structure_new_empty (NNS_MIMETYPE_TENSORS);
916 
917  if (config->info.num_tensors > 0) {
918  g_autofree gchar *type_str =
920 
921  /* Set GstCaps */
922  {
923  g_autofree gchar *dim_str =
925 
926  gst_caps_set_simple (caps, "num_tensors", G_TYPE_INT,
927  config->info.num_tensors, NULL);
928  gst_caps_set_simple (caps, "dimensions", G_TYPE_STRING, dim_str, NULL);
929  gst_caps_set_simple (caps, "types", G_TYPE_STRING, type_str, NULL);
930  }
931 
932  /* Set GstStructure */
933  if (structure) {
934  g_autofree gchar *dim_str =
937 
938  gst_structure_set (structure, "num_tensors", G_TYPE_INT,
939  config->info.num_tensors, NULL);
940  gst_structure_set (structure, "dimensions", G_TYPE_STRING, dim_str, NULL);
941  gst_structure_set (structure, "types", G_TYPE_STRING, type_str, NULL);
942  }
943  }
944 
945  if (config->rate_n >= 0 && config->rate_d > 0) {
946  gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
947  config->rate_n, config->rate_d, NULL);
948 
949  if (structure)
950  gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
951  config->rate_n, config->rate_d, NULL);
952  }
953 
954  if (structure)
955  gst_caps_append_structure (caps, structure);
956 
957  return caps;
958 }
959 
963 static GstCaps *
965 {
966  GstCaps *caps;
967 
968  caps = gst_caps_from_string (GST_TENSORS_FLEX_CAP_DEFAULT);
969 
970  if (config->rate_n >= 0 && config->rate_d > 0) {
971  gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
972  config->rate_n, config->rate_d, NULL);
973  }
974 
975  return caps;
976 }
977 
983 gboolean
984 gst_structure_is_tensor_stream (const GstStructure * structure)
985 {
986  const gchar *name;
987 
988  name = gst_structure_get_name (structure);
989  g_return_val_if_fail (name != NULL, FALSE);
990 
991  return (g_str_equal (name, NNS_MIMETYPE_TENSOR) ||
992  g_str_equal (name, NNS_MIMETYPE_TENSORS));
993 }
994 
1000 media_type
1001 gst_structure_get_media_type (const GstStructure * structure)
1002 {
1003  const gchar *name;
1004 
1005  name = gst_structure_get_name (structure);
1006 
1007  g_return_val_if_fail (name != NULL, _NNS_MEDIA_INVALID);
1008 
1009  if (g_str_has_prefix (name, "video/")) {
1010  return _NNS_VIDEO;
1011  }
1012 
1013  if (g_str_has_prefix (name, "audio/")) {
1014  return _NNS_AUDIO;
1015  }
1016 
1017  if (g_str_has_prefix (name, "text/")) {
1018  return _NNS_TEXT;
1019  }
1020 
1021  if (g_str_equal (name, "application/octet-stream")) {
1022  return _NNS_OCTET;
1023  }
1024 
1025  if (gst_structure_is_tensor_stream (structure)) {
1026  return _NNS_TENSOR;
1027  }
1028 
1029  /* unknown or unsupported type */
1030  return _NNS_MEDIA_INVALID;
1031 }
1032 
1040 gboolean
1042  gboolean * is_fixed)
1043 {
1044  GstCaps *peer_caps;
1045  GstStructure *structure;
1046  gboolean ret = FALSE;
1047 
1048  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1049  g_return_val_if_fail (config != NULL, FALSE);
1050 
1051  gst_tensors_config_init (config);
1052 
1053  if ((peer_caps = gst_pad_peer_query_caps (pad, NULL))) {
1054  if (gst_caps_get_size (peer_caps) > 0) {
1055  structure = gst_caps_get_structure (peer_caps, 0);
1056  ret = gst_tensors_config_from_structure (config, structure);
1057  }
1058 
1059  if (ret && is_fixed)
1060  *is_fixed = gst_caps_is_fixed (peer_caps);
1061 
1062  gst_caps_unref (peer_caps);
1063  }
1064 
1065  return ret;
1066 }
1067 
1071 static gboolean
1072 _is_structure_dimension_same (GstStructure * st1, GstStructure * st2,
1073  const gchar * fieldname)
1074 {
1075  const char *dim_str1;
1076  const char *dim_str2;
1077 
1078  g_return_val_if_fail (gst_structure_has_field (st1, fieldname), FALSE);
1079  g_return_val_if_fail (gst_structure_has_field (st2, fieldname), FALSE);
1080 
1081  dim_str1 = gst_structure_get_string (st1, fieldname);
1082  dim_str2 = gst_structure_get_string (st2, fieldname);
1083 
1084  return gst_tensor_dimension_string_is_equal (dim_str1, dim_str2);
1085 }
1086 
1092 void
1093 gst_tensor_caps_update_dimension (GstCaps * caps, GstCaps * filter)
1094 {
1095  GstStructure *st_caps, *st_filter;
1096  guint i, j;
1097 
1098  g_return_if_fail (GST_IS_CAPS (caps));
1099  g_return_if_fail (GST_IS_CAPS (filter));
1100 
1101  for (i = 0; i < gst_caps_get_size (caps); i++) {
1102  st_caps = gst_caps_get_structure (caps, i);
1103 
1104  if (!gst_structure_is_tensor_stream (st_caps))
1105  continue;
1106 
1107  for (j = 0; j < gst_caps_get_size (filter); j++) {
1108  st_filter = gst_caps_get_structure (filter, j);
1109 
1110  if (!gst_structure_is_tensor_stream (st_filter))
1111  continue;
1112 
1113  /* other/tensor */
1114  if (gst_structure_has_field (st_caps, "dimension")
1115  && gst_structure_has_field (st_filter, "dimension")) {
1116  /* update dimensions for negotiation */
1117  if (_is_structure_dimension_same (st_caps, st_filter, "dimension")) {
1118  gst_structure_set (st_caps, "dimension", G_TYPE_STRING,
1119  gst_structure_get_string (st_filter, "dimension"), NULL);
1120  }
1121  }
1122  /* other/tensors */
1123  else if (gst_structure_has_field (st_caps, "dimensions")
1124  && gst_structure_has_field (st_filter, "dimensions")) {
1125  /* update dimensions for negotiation */
1126  if (_is_structure_dimension_same (st_caps, st_filter, "dimensions")) {
1127  gst_structure_set (st_caps, "dimensions", G_TYPE_STRING,
1128  gst_structure_get_string (st_filter, "dimensions"), NULL);
1129  }
1130  }
1131  }
1132  }
1133 }
1134 
1141 gboolean
1142 gst_tensor_caps_can_intersect (GstCaps * caps1, GstCaps * caps2)
1143 {
1144  GstStructure *structure1;
1145  GstStructure *structure2;
1146  GstStructure *structure_copy1;
1147  GstStructure *structure_copy2;
1148 
1149  const gchar *name1;
1150  const gchar *name2;
1151 
1152  gboolean intersectable;
1153 
1154  if (gst_caps_can_intersect (caps1, caps2))
1155  return TRUE;
1156 
1157  structure1 = gst_caps_get_structure (caps1, 0);
1158  structure2 = gst_caps_get_structure (caps2, 0);
1159 
1160  if (!gst_structure_is_tensor_stream (structure1)
1161  || !gst_structure_is_tensor_stream (structure2))
1162  return FALSE;
1163 
1164  name1 = gst_structure_get_name (structure1);
1165  name2 = gst_structure_get_name (structure2);
1166 
1167  if (!g_str_equal (name1, name2))
1168  return FALSE;
1169 
1170  /* other/tensor */
1171  if (g_str_equal (name1, NNS_MIMETYPE_TENSOR)) {
1172  if (gst_structure_has_field (structure1, "dimension")
1173  && gst_structure_has_field (structure2, "dimension")) {
1174  if (!_is_structure_dimension_same (structure1, structure2, "dimension"))
1175  return FALSE;
1176  }
1177  }
1178  /* other/tensors */
1179  else if (gst_structure_has_field (structure1, "dimensions")
1180  && gst_structure_has_field (structure2, "dimensions")) {
1181  if (!_is_structure_dimension_same (structure1, structure2, "dimensions"))
1182  return FALSE;
1183  }
1184 
1185  structure_copy1 = gst_structure_copy (structure1);
1186  structure_copy2 = gst_structure_copy (structure2);
1187 
1188  gst_structure_remove_field (structure_copy1, "dimension");
1189  gst_structure_remove_field (structure_copy1, "dimensions");
1190  gst_structure_remove_field (structure_copy2, "dimension");
1191  gst_structure_remove_field (structure_copy2, "dimensions");
1192 
1193  intersectable =
1194  gst_structure_can_intersect (structure_copy1, structure_copy2);
1195 
1196  gst_structure_free (structure_copy1);
1197  gst_structure_free (structure_copy2);
1198 
1199  return intersectable;
1200 }
1201 
1208 GstCaps *
1210 {
1211  GstCaps *caps = NULL;
1212  GstCaps *templ;
1213  gboolean is_flexible, peer_is_flexible, peer_has_tensor_caps;
1214  GstCaps *peer_caps;
1215 
1216  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1217  g_return_val_if_fail (config != NULL, NULL);
1218 
1219  templ = gst_pad_get_pad_template_caps (pad);
1220 
1221  /* check peer caps */
1222  peer_is_flexible = peer_has_tensor_caps = FALSE;
1223 
1224  peer_caps = gst_pad_peer_query_caps (pad, NULL);
1225  if (peer_caps && gst_caps_get_size (peer_caps) > 0) {
1226  GstCaps *tmp;
1227  GstStructure *st;
1228  GstTensorsConfig peer_config;
1229 
1230  tmp = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT);
1231  peer_has_tensor_caps = gst_caps_can_intersect (tmp, peer_caps);
1232  gst_caps_unref (tmp);
1233 
1234  st = gst_caps_get_structure (peer_caps, 0);
1235  if (gst_tensors_config_from_structure (&peer_config, st))
1236  peer_is_flexible = gst_tensors_config_is_flexible (&peer_config);
1237  gst_tensors_config_free (&peer_config);
1238  }
1239 
1240  /* other/tensors (flexible) */
1241  is_flexible = gst_tensors_config_is_flexible (config);
1242 
1243  if (is_flexible || peer_is_flexible) {
1244  caps = _get_flexible_caps (config);
1245  goto intersectable;
1246  }
1247 
1248  /* other/tensor */
1249  if (config->info.num_tensors == 1 && peer_has_tensor_caps) {
1250  caps = _get_tensor_caps (config);
1251  if (peer_caps)
1252  gst_tensor_caps_update_dimension (caps, peer_caps);
1253 
1254  if (gst_caps_can_intersect (caps, templ))
1255  goto done;
1256 
1257  gst_caps_unref (caps);
1258  }
1259 
1260  /* other/tensors (static) */
1261  caps = _get_tensors_caps (config);
1262  if (peer_caps)
1263  gst_tensor_caps_update_dimension (caps, peer_caps);
1264 
1265 intersectable:
1266  if (!gst_caps_can_intersect (caps, templ)) {
1267  gst_caps_unref (caps);
1268  caps = NULL;
1269  }
1270 
1271 done:
1272  gst_caps_unref (templ);
1273  if (peer_caps)
1274  gst_caps_unref (peer_caps);
1275  caps = gst_caps_truncate (caps);
1276  return caps;
1277 }
1278 
1285 GstCaps *
1287  const GstTensorsConfig * config)
1288 {
1289  GstCaps *caps, *tmp;
1290  GstCaps *templ;
1291 
1292  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1293  g_return_val_if_fail (config != NULL, NULL);
1294 
1295  caps = gst_caps_new_empty ();
1296  templ = gst_pad_get_pad_template_caps (pad);
1297 
1298  /* append caps for static tensor */
1299  if (gst_tensors_config_is_static (config)) {
1300  /* other/tensor */
1301  if ((tmp = _get_tensor_caps (config)) != NULL) {
1302  if (gst_caps_can_intersect (tmp, templ))
1303  gst_caps_append (caps, tmp);
1304  else
1305  gst_caps_unref (tmp);
1306  }
1307 
1308  /* other/tensors */
1309  if ((tmp = _get_tensors_caps (config)) != NULL) {
1310  if (gst_caps_can_intersect (tmp, templ))
1311  gst_caps_append (caps, tmp);
1312  else
1313  gst_caps_unref (tmp);
1314  }
1315  }
1316 
1317  /* caps for flexible tensor */
1318  if ((tmp = _get_flexible_caps (config)) != NULL) {
1319  if (gst_caps_can_intersect (tmp, templ))
1320  gst_caps_append (caps, tmp);
1321  else
1322  gst_caps_unref (tmp);
1323  }
1324 
1325  /* if no possible caps for given config, return null. */
1326  if (gst_caps_is_empty (caps)) {
1327  gst_caps_unref (caps);
1328  caps = NULL;
1329  }
1330 
1331  gst_caps_unref (templ);
1332  return caps;
1333 }
1334 
1344 {
1345  GstCaps *caps;
1347 
1348  g_return_val_if_fail (GST_IS_PAD (pad), _NNS_TENSOR_FORMAT_END);
1349 
1350  caps = gst_pad_get_current_caps (pad);
1351  if (caps) {
1352  GstStructure *structure;
1353  GstTensorsConfig config;
1354 
1355  structure = gst_caps_get_structure (caps, 0);
1356  if (gst_tensors_config_from_structure (&config, structure)) {
1357  ret = config.info.format;
1358  }
1359  gst_caps_unref (caps);
1360  gst_tensors_config_free (&config);
1361  }
1362 
1363  return ret;
1364 }
1365 
1371 GstCaps *
1373 {
1374  GstCaps *caps;
1375 
1376  g_return_val_if_fail (config != NULL, NULL);
1377 
1378  if (gst_tensors_config_is_flexible (config)) {
1379  caps = _get_flexible_caps (config);
1380  } else {
1381  caps = _get_tensors_caps (config);
1382  }
1383 
1384  caps = gst_caps_truncate (caps);
1385 
1386  return caps;
1387 }
1388 
1394 GstCaps *
1396 {
1397  GstCaps *caps;
1398  g_return_val_if_fail (config != NULL, NULL);
1399 
1400  caps = _get_tensor_caps (config);
1401  caps = gst_caps_truncate (caps);
1402 
1403  return caps;
1404 }
1405 
1412 gboolean
1414  const GstStructure * structure)
1415 {
1416  const gchar *name;
1418 
1419  g_return_val_if_fail (config != NULL, FALSE);
1420  gst_tensors_config_init (config);
1421 
1422  g_return_val_if_fail (structure != NULL, FALSE);
1423 
1424  name = gst_structure_get_name (structure);
1425 
1426  if (g_str_equal (name, NNS_MIMETYPE_TENSOR)) {
1427  /* other/tensor is always static */
1428  config->info.num_tensors = 1;
1429 
1430  if (gst_structure_has_field (structure, "dimension")) {
1431  const gchar *dim_str = gst_structure_get_string (structure, "dimension");
1432  gst_tensor_parse_dimension (dim_str, config->info.info[0].dimension);
1433  }
1434 
1435  if (gst_structure_has_field (structure, "type")) {
1436  const gchar *type_str = gst_structure_get_string (structure, "type");
1437  config->info.info[0].type = gst_tensor_get_type (type_str);
1438  }
1439  } else if (g_str_equal (name, NNS_MIMETYPE_TENSORS)) {
1440  if (gst_structure_has_field (structure, "format")) {
1441  const gchar *format_str;
1442 
1443  format_str = gst_structure_get_string (structure, "format");
1444  format = gst_tensor_get_format (format_str);
1445 
1446  if (format == _NNS_TENSOR_FORMAT_END) {
1447  GST_INFO
1448  ("Invalid format %s, it should be one of %s. Suppose tensor format is static.",
1449  _STR_NULL (format_str), GST_TENSOR_FORMAT_ALL);
1450  } else {
1451  config->info.format = format;
1452  }
1453  }
1454 
1455  if (config->info.format == _NNS_TENSOR_FORMAT_STATIC) {
1456  gst_structure_get_int (structure, "num_tensors",
1457  (gint *) (&config->info.num_tensors));
1458 
1459  /* parse dimensions */
1460  if (gst_structure_has_field (structure, "dimensions")) {
1461  const gchar *dims_str;
1462  guint num_dims;
1463 
1464  dims_str = gst_structure_get_string (structure, "dimensions");
1465  num_dims =
1466  gst_tensors_info_parse_dimensions_string (&config->info, dims_str);
1467 
1468  if (config->info.num_tensors != num_dims) {
1469  nns_logw ("Invalid param, dimensions (%d) tensors (%d)\n",
1470  num_dims, config->info.num_tensors);
1471  }
1472  }
1473 
1474  /* parse types */
1475  if (gst_structure_has_field (structure, "types")) {
1476  const gchar *types_str;
1477  guint num_types;
1478 
1479  types_str = gst_structure_get_string (structure, "types");
1480  num_types =
1481  gst_tensors_info_parse_types_string (&config->info, types_str);
1482 
1483  if (config->info.num_tensors != num_types) {
1484  nns_logw ("Invalid param, types (%d) tensors (%d)\n",
1485  num_types, config->info.num_tensors);
1486  }
1487  }
1488  }
1489  } else {
1490  nns_logw ("Unsupported type = %s\n", name ? name : "Unknown");
1491  return FALSE;
1492  }
1493 
1494  if (gst_structure_has_field (structure, "framerate")) {
1495  gst_structure_get_fraction (structure, "framerate", &config->rate_n,
1496  &config->rate_d);
1497  }
1498 
1499  return TRUE;
1500 }
1501 
1508 gboolean
1510 {
1511  GstMapInfo map;
1512  gsize hsize, msize;
1513  gboolean ret;
1514 
1515  g_return_val_if_fail (mem != NULL, FALSE);
1516  g_return_val_if_fail (meta != NULL, FALSE);
1517 
1519 
1520  /* Check header size of tensor-meta. */
1521  hsize = gst_tensor_meta_info_get_header_size (meta);
1522  msize = gst_memory_get_sizes (mem, NULL, NULL);
1523  if (msize < hsize)
1524  return FALSE;
1525 
1526  if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
1527  nns_loge ("Failed to get the meta, cannot map the memory.");
1528  return FALSE;
1529  }
1530 
1531  ret = gst_tensor_meta_info_parse_header (meta, map.data);
1532 
1533  gst_memory_unmap (mem, &map);
1534  return ret;
1535 }
1536 
1543 GstMemory *
1545 {
1546  GstMemory *new_mem = NULL;
1547  gsize msize, hsize;
1548  GstMapInfo old_map, new_map;
1549 
1550  g_return_val_if_fail (mem != NULL, NULL);
1551  g_return_val_if_fail (gst_tensor_meta_info_validate (meta), NULL);
1552 
1553  if (!gst_memory_map (mem, &old_map, GST_MAP_READ)) {
1554  nns_loge ("Failed to append header, cannot map the old memory.");
1555  return NULL;
1556  }
1557 
1558  /* memory size (header + old memory) */
1559  hsize = gst_tensor_meta_info_get_header_size (meta);
1560  msize = hsize + old_map.size;
1561 
1562  new_mem = gst_allocator_alloc (NULL, msize, NULL);
1563  if (!gst_memory_map (new_mem, &new_map, GST_MAP_WRITE)) {
1564  nns_loge ("Failed to append header, cannot map the new memory.");
1565  gst_memory_unmap (mem, &old_map);
1566  gst_memory_unref (new_mem);
1567  return NULL;
1568  }
1569 
1570  /* set header and copy old data */
1571  gst_tensor_meta_info_update_header (meta, new_map.data);
1572  memcpy (new_map.data + hsize, old_map.data, old_map.size);
1573 
1574  gst_memory_unmap (mem, &old_map);
1575  gst_memory_unmap (new_mem, &new_map);
1576  return new_mem;
1577 }
1578 
1585 GstMemory *
1586 gst_tensor_buffer_get_nth_memory (GstBuffer * buffer, const guint index)
1587 {
1588  guint i, num_tensors;
1589  gsize offset;
1590  GstMemory *extra_tensors_memory, *res_mem = NULL;
1591  GstMapInfo extra_tensors_map;
1592  GstTensorExtraInfo *extra_info;
1593 
1594  if (!GST_IS_BUFFER (buffer)) {
1595  nns_loge ("Failed to parse GstBuffer (invalid input buffer).");
1596  return NULL;
1597  }
1598 
1599  num_tensors = gst_tensor_buffer_get_count (buffer);
1600  if (index >= num_tensors) {
1601  nns_loge ("Invalid index %u, the number of tensors in the buffer is %u.",
1602  index, num_tensors);
1603  return NULL;
1604  }
1605 
1606  /* If num_tensors is less than or equal to NNS_TENSOR_MEMORY_MAX, it's trivial. */
1607  if (num_tensors <= NNS_TENSOR_MEMORY_MAX || index < NNS_TENSOR_MEMORY_MAX - 1) {
1608  return gst_buffer_get_memory (buffer, index);
1609  }
1610 
1611  /* If num_tensors is greater than NNS_TENSOR_MEMORY_MAX, we need to parse extra info. */
1612  extra_tensors_memory =
1613  gst_buffer_peek_memory (buffer, NNS_TENSOR_MEMORY_MAX - 1);
1614  if (!extra_tensors_memory) {
1615  nns_loge ("Failed to get %d-th memory", NNS_TENSOR_MEMORY_MAX);
1616  return NULL;
1617  }
1618 
1619  if (!gst_memory_map (extra_tensors_memory, &extra_tensors_map, GST_MAP_READ)) {
1620  nns_loge ("Failed to map %d-th memory", NNS_TENSOR_MEMORY_MAX);
1621  return NULL;
1622  }
1623 
1624  /* check header (extra info) of the memory */
1625  if (!gst_memory_map_is_extra_tensor (&extra_tensors_map)) {
1626  nns_loge ("Invalid extra header");
1627  goto done;
1628  }
1629 
1630  /* parse the memory */
1631  extra_info = (GstTensorExtraInfo *) extra_tensors_map.data;
1632  offset = sizeof (GstTensorExtraInfo);
1633 
1634  /* If index is NNS_TENSOR_MEMORY_MAX - 1 */
1635  if (index == NNS_TENSOR_MEMORY_MAX - 1) {
1636  res_mem =
1637  gst_memory_share (extra_tensors_memory, offset, extra_info->reserved);
1638  goto done;
1639  }
1640 
1641  offset += extra_info->reserved;
1642 
1643  for (i = 1; i <= index - NNS_TENSOR_MEMORY_MAX; ++i) {
1644  offset += gst_tensor_info_get_size (&extra_info->infos[i - 1]);
1645  }
1646 
1647  /* wrap it as GstMemory */
1648  res_mem =
1649  gst_memory_share (extra_tensors_memory, offset,
1650  gst_tensor_info_get_size (&extra_info->infos[index -
1652 
1653 done:
1654  gst_memory_unmap (extra_tensors_memory, &extra_tensors_map);
1655  return res_mem;
1656 }
1657 
1665 gboolean
1666 gst_tensor_buffer_append_memory (GstBuffer * buffer, GstMemory * memory,
1667  const GstTensorInfo * info)
1668 {
1669  guint num_mems, new_mem_index;
1670  GstMemory *new_memory = NULL, *last_memory = NULL;
1671  gsize offset, new_mem_size, last_mem_size;
1672  GstMapInfo new_memory_map, last_memory_map, incoming_memory_map;
1673  GstTensorExtraInfo *extra_info;
1674  GstTensorMetaInfo meta;
1675  gboolean is_extra, is_static;
1676  gboolean appended = FALSE;
1677 
1678  if (!GST_IS_BUFFER (buffer)) {
1679  nns_loge ("Failed to append memory, given buffer is invalid.");
1680  goto failed;
1681  }
1682 
1683  if (!memory) {
1684  nns_loge ("Failed to append memory, given memory is NULL.");
1685  goto failed;
1686  }
1687 
1688  if (gst_tensor_meta_info_parse_memory (&meta, memory)) {
1689  is_static = (meta.format == _NNS_TENSOR_FORMAT_STATIC);
1690  } else {
1691  /* Suppose given memory is static tensor. */
1692  is_static = TRUE;
1693 
1694  /* Error case if given tensor-info is invalid. */
1695  if (!gst_tensor_info_validate (info)) {
1696  nns_loge ("Failed to get tensor info (invalid input info).");
1697  goto failed;
1698  }
1699  }
1700 
1701  num_mems = gst_buffer_n_memory (buffer);
1702 
1703  /* trivial call to gst_buffer_append_memory */
1704  if (num_mems < NNS_TENSOR_MEMORY_MAX) {
1705  gst_buffer_append_memory (buffer, memory);
1706  return TRUE;
1707  }
1708 
1709  /* given buffer has NNS_TENSOR_MEMORY_MAX memory blocks */
1710  last_memory = gst_buffer_peek_memory (buffer, num_mems - 1);
1711  if (!last_memory) {
1712  nns_loge ("Failed to get last memory");
1713  goto failed;
1714  }
1715 
1716  if (!gst_memory_map (last_memory, &last_memory_map, GST_MAP_READ)) {
1717  nns_loge ("Failed to map last memory");
1718  last_memory = NULL;
1719  goto failed;
1720  }
1721 
1722  new_mem_size = last_mem_size = gst_memory_get_sizes (last_memory, NULL, NULL);
1723 
1724  /* if the memory does not have proper header, append it */
1725  is_extra = gst_memory_map_is_extra_tensor (&last_memory_map);
1726  if (!is_extra) {
1727  new_mem_size += sizeof (GstTensorExtraInfo);
1728  }
1729 
1730  new_mem_size += gst_memory_get_sizes (memory, NULL, NULL);
1731 
1732  new_memory = gst_allocator_alloc (NULL, new_mem_size, NULL);
1733  if (!new_memory) {
1734  nns_loge ("Failed to allocate memory for extra tensors.");
1735  goto failed;
1736  }
1737 
1738  if (!gst_memory_map (new_memory, &new_memory_map, GST_MAP_WRITE)) {
1739  nns_loge ("Failed to map extra memory");
1740  gst_memory_unref (new_memory);
1741  new_memory = NULL;
1742  goto failed;
1743  }
1744 
1745  if (!gst_memory_map (memory, &incoming_memory_map, GST_MAP_READ)) {
1746  nns_loge ("Failed to map incoming memory");
1747  goto failed;
1748  }
1749 
1750  extra_info = (GstTensorExtraInfo *) new_memory_map.data;
1751 
1752  /* if the last_memory does not have proper header, append it */
1753  if (!is_extra) {
1754  gst_tensor_extra_info_init (extra_info, last_mem_size);
1755  offset = sizeof (GstTensorExtraInfo);
1756  } else {
1757  offset = 0;
1758  }
1759 
1760  /* copy last_memory into new_memory */
1761  memcpy (new_memory_map.data + offset, last_memory_map.data,
1762  last_memory_map.size);
1763 
1764  /* copy incoming_memory into new_memory */
1765  new_mem_index = extra_info->num_extra_tensors;
1766  extra_info->num_extra_tensors += 1;
1767 
1768  /* Copy tensor info into extra. */
1769  if (is_static) {
1770  gst_tensor_info_copy (&extra_info->infos[new_mem_index], info);
1771 
1776  g_free (extra_info->infos[new_mem_index].name);
1777  extra_info->infos[new_mem_index].name = NULL;
1778  } else {
1779  gst_tensor_meta_info_convert (&meta, &extra_info->infos[new_mem_index]);
1780  }
1781 
1782  memcpy (new_memory_map.data + offset + last_memory_map.size,
1783  incoming_memory_map.data, incoming_memory_map.size);
1784 
1785  gst_memory_unmap (memory, &incoming_memory_map);
1786  gst_memory_unmap (last_memory, &last_memory_map);
1787  last_memory = NULL;
1788 
1789  gst_buffer_replace_memory (buffer, num_mems - 1, new_memory);
1790  appended = TRUE;
1791 
1792 failed:
1793  if (new_memory) {
1794  gst_memory_unmap (new_memory, &new_memory_map);
1795  if (!appended)
1796  gst_memory_unref (new_memory);
1797  }
1798 
1799  if (last_memory)
1800  gst_memory_unmap (last_memory, &last_memory_map);
1801 
1802  /* Release incoming memory even if failed to append it into buffer. */
1803  if (memory)
1804  gst_memory_unref (memory);
1805 
1806  return appended;
1807 }
1808 
1812 guint
1813 gst_tensor_buffer_get_count (GstBuffer * buffer)
1814 {
1815  guint num_mems;
1816  GstMemory *mem;
1817  GstMapInfo map;
1818  GstTensorExtraInfo *extra_info;
1819 
1820  g_return_val_if_fail (buffer != NULL, 0);
1821 
1822  num_mems = gst_buffer_n_memory (buffer);
1823  if (num_mems < NNS_TENSOR_MEMORY_MAX) {
1824  return num_mems;
1825  }
1826 
1827  /* num_mems == NNS_TENSOR_MEMORY_MAX */
1828  mem = gst_buffer_peek_memory (buffer, num_mems - 1);
1829  if (!mem) {
1830  nns_loge ("Failed to get the last memory.");
1831  return 0;
1832  }
1833 
1834  if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
1835  nns_loge ("Failed to map the last memory.");
1836  return 0;
1837  }
1838 
1839  if (gst_memory_map_is_extra_tensor (&map)) {
1840  extra_info = (GstTensorExtraInfo *) map.data;
1841  num_mems = extra_info->num_extra_tensors + NNS_TENSOR_MEMORY_MAX;
1842  } else {
1843  nns_logi ("The last memory does not have extra tensors header. "
1844  "Assuming the number of tensors is %d.", num_mems);
1845  }
1846 
1847  gst_memory_unmap (mem, &map);
1848 
1849  return num_mems;
1850 }
1851 
1861 static void
1862 set_property_value (GValue * prop_value, const GParamSpec * param_spec,
1863  const gchar * property_value)
1864 {
1865  GType value_type = G_PARAM_SPEC_VALUE_TYPE (param_spec);
1866  g_value_init (prop_value, value_type);
1867 
1868  if (value_type == G_TYPE_BOOLEAN) {
1869  gboolean value = g_ascii_strcasecmp (property_value, "true") == 0;
1870  g_value_set_boolean (prop_value, value);
1871  } else if (value_type == G_TYPE_INT) {
1872  gint value = atoi (property_value);
1873  g_value_set_int (prop_value, value);
1874  } else if (value_type == G_TYPE_UINT) {
1875  guint value = atoi (property_value);
1876  g_value_set_uint (prop_value, value);
1877  } else if (value_type == G_TYPE_FLOAT) {
1878  gfloat value = atof (property_value);
1879  g_value_set_float (prop_value, value);
1880  } else if (value_type == G_TYPE_DOUBLE) {
1881  gdouble value = atof (property_value);
1882  g_value_set_double (prop_value, value);
1883  } else {
1884  g_value_set_string (prop_value, property_value);
1885  }
1886 }
1887 
1901 void
1902 gst_tensor_parse_config_file (const gchar * config_path, const GObject * object)
1903 {
1904  g_autofree gchar *config_data = NULL;
1905  g_auto (GStrv) lines = NULL;
1906  GStrv line = NULL;
1907  GError *error = NULL;
1908  GObjectClass *g_object_class = G_OBJECT_GET_CLASS (object);
1909 
1910  if (!g_file_get_contents (config_path, &config_data, NULL, &error)) {
1911  GST_DEBUG ("Failed to read config file: %s\n", error->message);
1912  g_error_free (error);
1913  return;
1914  }
1915 
1916  lines = g_strsplit (config_data, "\n", -1);
1917 
1919  for (line = lines; *line; ++line) {
1920  g_auto (GStrv) parts = g_strsplit (*line, "=", 2);
1921 
1922  if (g_strv_length (parts) == 2) {
1923  g_autofree gchar *property_name = g_strstrip (g_strdup (parts[0]));
1924  g_autofree gchar *property_value = g_strstrip (g_strdup (parts[1]));
1925 
1926  GParamSpec *pdata =
1927  g_object_class_find_property (g_object_class, property_name);
1928 
1929  if (pdata != NULL) {
1930  GValue prop_value = G_VALUE_INIT;
1931  set_property_value (&prop_value, pdata, property_value);
1932  g_object_set_property (G_OBJECT (object), pdata->name, &prop_value);
1933  g_value_unset (&prop_value);
1934  }
1935  }
1936  }
1937 }
find_key_strv
gint find_key_strv(const gchar **strv, const gchar *key)
Find the index value of the given key string array.
Definition: nnstreamer_plugin_api_util_impl.c:1586
SYNC_BASEPAD
@ SYNC_BASEPAD
Definition: tensor_common.h:66
gst_tensor_dimension_string_is_equal
gboolean gst_tensor_dimension_string_is_equal(const gchar *dimstr1, const gchar *dimstr2)
Compare dimension strings.
Definition: nnstreamer_plugin_api_util_impl.c:1140
gst_tensor_get_type
tensor_type gst_tensor_get_type(const gchar *typestr)
Get tensor type from string input.
Definition: nnstreamer_plugin_api_util_impl.c:1218
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
GST_TENSOR_CAP_DEFAULT
#define GST_TENSOR_CAP_DEFAULT
Default static capability for other/tensor.
Definition: tensor_typedef.h:78
gst_tensor_buffer_from_config
GstBuffer * gst_tensor_buffer_from_config(GstBuffer *in, GstTensorsConfig *config)
Configure gst-buffer with tensors information. NNStreamer handles single memory chunk as single tenso...
Definition: nnstreamer_plugin_api_impl.c:535
g_assert
g_assert(sizeof(DTYPE_UNSIGNED)==sizeof(DTYPE_SIGNED))
gst_tensor_aggregation_get_adapter
GstAdapter * gst_tensor_aggregation_get_adapter(GHashTable *table, const guint32 key)
Gets adapter from hash table.
Definition: nnstreamer_plugin_api_impl.c:790
gst_tensor_dimension_is_valid
gboolean gst_tensor_dimension_is_valid(const tensor_dim dim)
Check the tensor dimension is valid.
Definition: nnstreamer_plugin_api_util_impl.c:940
gst_tensor_get_type_string
const gchar * gst_tensor_get_type_string(tensor_type type)
Get type string of tensor type.
Definition: nnstreamer_plugin_api_util_impl.c:1296
SYNC_NOSYNC
@ SYNC_NOSYNC
Definition: tensor_common.h:64
_tensor_time_sync_data::data_basepad
tensor_sync_basepad_data data_basepad
Definition: tensor_common.h:86
GstTensorInfo::name
char * name
Definition: tensor_typedef.h:263
data
svtc_1 data
Definition: gsttensor_if.c:844
gst_tensor_meta_info_parse_memory
gboolean gst_tensor_meta_info_parse_memory(GstTensorMetaInfo *meta, GstMemory *mem)
Parse memory and fill the tensor meta.
Definition: nnstreamer_plugin_api_impl.c:1509
GstTensorInfo
Internal data structure for tensor info.
Definition: tensor_typedef.h:261
NNS_TENSOR_MEMORY_MAX
#define NNS_TENSOR_MEMORY_MAX
This value, 16, can be checked with gst_buffer_get_max_memory(), which is GST_BUFFER_MEM_MAX in gstre...
Definition: tensor_typedef.h:52
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
GST_TENSORS_FLEX_CAP_DEFAULT
#define GST_TENSORS_FLEX_CAP_DEFAULT
Caps string for the caps template of flexible tensors. This mimetype handles non-static,...
Definition: tensor_typedef.h:123
gst_tensors_config_from_structure
gboolean gst_tensors_config_from_structure(GstTensorsConfig *config, const GstStructure *structure)
Parse structure and set tensors config (for other/tensors)
Definition: nnstreamer_plugin_api_impl.c:1413
gst_structure_is_tensor_stream
gboolean gst_structure_is_tensor_stream(const GstStructure *structure)
Check given mimetype is tensor stream.
Definition: nnstreamer_plugin_api_impl.c:984
set_property_value
static void set_property_value(GValue *prop_value, const GParamSpec *param_spec, const gchar *property_value)
Sets the value of a property based on the specified property value and GParamSpec.
Definition: nnstreamer_plugin_api_impl.c:1862
gst_structure_get_media_type
media_type gst_structure_get_media_type(const GstStructure *structure)
Get media type from structure.
Definition: nnstreamer_plugin_api_impl.c:1001
gst_tensor_get_rank_dimension_string
gchar * gst_tensor_get_rank_dimension_string(const tensor_dim dim, const unsigned int rank)
Get dimension string from given tensor dimension and rank count.
Definition: nnstreamer_plugin_api_util_impl.c:1107
gst_tensor_time_sync_set_option_data
gboolean gst_tensor_time_sync_set_option_data(tensor_time_sync_data *sync)
Setup time sync option.
Definition: nnstreamer_plugin_api_impl.c:126
gst_tensor_aggregation_free_data
static void gst_tensor_aggregation_free_data(gpointer data)
Internal function to free aggregation data.
Definition: nnstreamer_plugin_api_impl.c:668
FALSE
return FALSE
Definition: gsttensor_transform.c:590
gst_tensor_buffer_append_memory
gboolean gst_tensor_buffer_append_memory(GstBuffer *buffer, GstMemory *memory, const GstTensorInfo *info)
Append memory to given buffer.
Definition: nnstreamer_plugin_api_impl.c:1666
gst_tensors_config_from_peer
gboolean gst_tensors_config_from_peer(GstPad *pad, GstTensorsConfig *config, gboolean *is_fixed)
Parse caps from peer pad and set tensors config.
Definition: nnstreamer_plugin_api_impl.c:1041
GstTensorExtraInfo::version
uint32_t version
Definition: nnstreamer_plugin_api_impl.c:42
GstTensorsInfo
Internal meta data exchange format for a other/tensors instance.
Definition: tensor_typedef.h:273
gst_tensor_meta_info_update_header
gboolean gst_tensor_meta_info_update_header(GstTensorMetaInfo *meta, gpointer header)
Update header from tensor meta.
Definition: nnstreamer_plugin_api_util_impl.c:1505
gst_tensor_time_sync_buffer_from_collectpad
gboolean gst_tensor_time_sync_buffer_from_collectpad(GstCollectPads *collect, tensor_time_sync_data *sync, GstClockTime current_time, GstBuffer *tensors_buf, GstTensorsConfig *configs, gboolean *is_eos)
A function call to make tensors from collected pads. It decide which buffer is going to be used accor...
Definition: nnstreamer_plugin_api_impl.c:332
_NNS_VIDEO
@ _NNS_VIDEO
Definition: tensor_typedef.h:182
gst_tensor_get_format
tensor_format gst_tensor_get_format(const gchar *format_str)
Get tensor format from string input.
Definition: nnstreamer_plugin_api_util_impl.c:1309
_NNS_OCTET
@ _NNS_OCTET
Definition: tensor_typedef.h:185
gst_tensors_info_validate
gboolean gst_tensors_info_validate(const GstTensorsInfo *info)
Check the tensors info is valid.
Definition: nnstreamer_plugin_api_util_impl.c:404
gst_memory_map_is_extra_tensor
static gboolean gst_memory_map_is_extra_tensor(GstMapInfo *map)
Check if given memory has extra tensors.
Definition: nnstreamer_plugin_api_impl.c:54
_tensor_time_sync_data
Tensor Merge/Mux time sync data.
Definition: tensor_common.h:82
gst_tensor_meta_info_validate
gboolean gst_tensor_meta_info_validate(GstTensorMetaInfo *meta)
Check the meta info is valid.
Definition: nnstreamer_plugin_api_util_impl.c:1414
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
GstTensorExtraInfo::reserved
uint64_t reserved
Definition: nnstreamer_plugin_api_impl.c:44
GstTensorExtraInfo
Data structure to describe a "extra" tensor data. This represents the information of the NNS_TENSOR_S...
Definition: nnstreamer_plugin_api_impl.c:39
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_tensor_caps_update_dimension
void gst_tensor_caps_update_dimension(GstCaps *caps, GstCaps *filter)
Update caps dimensions for negotiation.
Definition: nnstreamer_plugin_api_impl.c:1093
gst_tensor_time_sync_get_mode_string
const gchar * gst_tensor_time_sync_get_mode_string(tensor_time_sync_mode mode)
Get the time-sync mode string.
Definition: nnstreamer_plugin_api_impl.c:115
gst_tensor_meta_info_get_data_size
gsize gst_tensor_meta_info_get_data_size(GstTensorMetaInfo *meta)
Get the data size calculated from tensor meta.
Definition: nnstreamer_plugin_api_util_impl.c:1477
GstTensorMetaInfo
Data structure to describe a tensor data. This represents the basic information of a memory block for...
Definition: tensor_typedef.h:310
SYNC_END
@ SYNC_END
Definition: tensor_common.h:68
GstTensorsConfig::rate_d
int rate_d
Definition: tensor_typedef.h:288
SYNC_SLOWEST
@ SYNC_SLOWEST
Definition: tensor_common.h:65
gst_tensor_parse_dimension
guint gst_tensor_parse_dimension(const gchar *dimstr, tensor_dim dim)
Parse tensor dimension parameter string.
Definition: nnstreamer_plugin_api_util_impl.c:1040
gst_tensors_caps_from_config
GstCaps * gst_tensors_caps_from_config(const GstTensorsConfig *config)
Get caps from tensors config (for other/tensors)
Definition: nnstreamer_plugin_api_impl.c:1372
_NNS_TENSOR
@ _NNS_TENSOR
Definition: tensor_typedef.h:186
_gst_tensor_time_sync_is_eos
static gboolean _gst_tensor_time_sync_is_eos(GstCollectPads *collect, tensor_time_sync_data *sync, guint empty)
Internal function to detect EOS using the number of empty pads.
Definition: nnstreamer_plugin_api_impl.c:175
gst_tensors_info_get_types_string
gchar * gst_tensors_info_get_types_string(const GstTensorsInfo *info)
Get the string of types in tensors info.
Definition: nnstreamer_plugin_api_util_impl.c:714
nns_logi
#define nns_logi
Definition: nnstreamer_log.h:140
GST_TENSOR_FORMAT_ALL
#define GST_TENSOR_FORMAT_ALL
Possible tensor formats.
Definition: tensor_typedef.h:73
g_free
g_free(self->option[(opnum) - 1])
opnum: \
NNS_TENSOR_RANK_LIMIT_PREV
#define NNS_TENSOR_RANK_LIMIT_PREV
The old rank of tensor.
Definition: nnstreamer_plugin_api_impl.c:31
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
_get_flexible_caps
static GstCaps * _get_flexible_caps(const GstTensorsConfig *config)
Internal function to get caps for flexible tensor from config.
Definition: nnstreamer_plugin_api_impl.c:964
g_value_set_string
g_value_set_string(value, self->option[opnum - 1])
opnum: \
gst_tensor_meta_info_parse_header
gboolean gst_tensor_meta_info_parse_header(GstTensorMetaInfo *meta, gpointer header)
Parse header and fill the tensor meta.
Definition: nnstreamer_plugin_api_util_impl.c:1527
GstTensorsConfig::rate_n
int rate_n
Definition: tensor_typedef.h:287
_NNS_END
@ _NNS_END
Definition: tensor_typedef.h:152
_NNS_TENSOR_FORMAT_FLEXIBLE
@ _NNS_TENSOR_FORMAT_FLEXIBLE
Definition: tensor_typedef.h:196
gst_tensor_dimension_get_rank
guint gst_tensor_dimension_get_rank(const tensor_dim dim)
Get the rank of tensor dimension.
Definition: nnstreamer_plugin_api_util_impl.c:998
_get_tensors_caps
static GstCaps * _get_tensors_caps(const GstTensorsConfig *config)
Internal function to get caps for multi tensors from config.
Definition: nnstreamer_plugin_api_impl.c:904
GstTensorsInfo::info
GstTensorInfo info[NNS_TENSOR_MEMORY_MAX]
Definition: tensor_typedef.h:276
_gst_tensor_time_sync_buffer_update
static gboolean _gst_tensor_time_sync_buffer_update(GstCollectPads *collect, GstCollectData *data, GstClockTime current, GstClockTime base, tensor_time_sync_data *sync)
Internal function to update buffer in pad data based on the sync mode.
Definition: nnstreamer_plugin_api_impl.c:287
tensor_format
enum _tensor_format tensor_format
Data format of tensor stream in the pipeline.
AGGREGATION_DEFAULT_KEY
#define AGGREGATION_DEFAULT_KEY
Definition: nnstreamer_plugin_api_impl.c:662
_tensor_sync_basepad_data::duration
GstClockTime duration
Definition: tensor_common.h:76
gst_tensors_config_free
void gst_tensors_config_free(GstTensorsConfig *config)
Free allocated data in tensors config structure.
Definition: nnstreamer_plugin_api_util_impl.c:845
gst_tensor_pad_get_format
tensor_format gst_tensor_pad_get_format(GstPad *pad)
Get tensor format of current pad caps.
Definition: nnstreamer_plugin_api_impl.c:1343
_NNS_TENSOR_FORMAT_STATIC
@ _NNS_TENSOR_FORMAT_STATIC
Definition: tensor_typedef.h:195
gst_tensor_info_convert_to_meta
gboolean gst_tensor_info_convert_to_meta(GstTensorInfo *info, GstTensorMetaInfo *meta)
Convert GstTensorInfo structure to GstTensorMetaInfo.
Definition: nnstreamer_plugin_api_util_impl.c:260
gst_tensor_aggregation_clear_internal
static void gst_tensor_aggregation_clear_internal(gpointer key, gpointer value, gpointer user_data)
Internal function to remove all buffers from aggregation data.
Definition: nnstreamer_plugin_api_impl.c:718
gst_tensor_meta_info_convert
gboolean gst_tensor_meta_info_convert(GstTensorMetaInfo *meta, GstTensorInfo *info)
Convert GstTensorMetaInfo structure to GstTensorInfo.
Definition: nnstreamer_plugin_api_util_impl.c:1562
gst_tensor_get_dimension_string
gchar * gst_tensor_get_dimension_string(const tensor_dim dim)
Get dimension string from given tensor dimension.
Definition: nnstreamer_plugin_api_util_impl.c:1083
_NNS_TEXT
@ _NNS_TEXT
Definition: tensor_typedef.h:184
GstTensorsConfig
Internal data structure for configured tensors info (for other/tensors).
Definition: tensor_typedef.h:284
GstTensorExtraInfo::num_extra_tensors
uint32_t num_extra_tensors
Definition: nnstreamer_plugin_api_impl.c:43
_is_structure_dimension_same
static gboolean _is_structure_dimension_same(GstStructure *st1, GstStructure *st2, const gchar *fieldname)
Check whether two structures have the same dimension.
Definition: nnstreamer_plugin_api_impl.c:1072
gst_tensor_info_init
void gst_tensor_info_init(GstTensorInfo *info)
Initialize the tensor info structure.
Definition: nnstreamer_plugin_api_util_impl.c:121
NNS_TENSOR_EXTRA_MAGIC
#define NNS_TENSOR_EXTRA_MAGIC
Definition: nnstreamer_plugin_api_impl.c:33
GstTensorCollectPadData::buffer
GstBuffer * buffer
Definition: tensor_common.h:96
TRUE
return TRUE
Definition: gsttensor_if.c:897
UNUSED
#define UNUSED(expr)
Definition: mqttcommon.h:19
_tensor_sync_basepad_data::sink_id
guint sink_id
Definition: tensor_common.h:75
gst_tensor_aggregation_init
GHashTable * gst_tensor_aggregation_init(void)
Gets new hash table for tensor aggregation.
Definition: nnstreamer_plugin_api_impl.c:737
nns_loge
#define nns_loge
Definition: nnstreamer_log.h:142
GstTensorCollectPadData
Internal data structure for Collect Pad in mux / merge.
Definition: tensor_common.h:93
gst_tensor_aggregation_add_data
static gst_tensor_aggregation_data_s * gst_tensor_aggregation_add_data(GHashTable *table, const guint32 key)
Internal function to add new aggregation data.
Definition: nnstreamer_plugin_api_impl.c:685
nnstreamer_util.h
Optional NNStreamer utility functions for sub-plugin writers and users.
gst_tensor_pad_possible_caps_from_config
GstCaps * gst_tensor_pad_possible_caps_from_config(GstPad *pad, const GstTensorsConfig *config)
Get all possible caps from tensors config. Unlike gst_tensor_pad_caps_from_config(),...
Definition: nnstreamer_plugin_api_impl.c:1286
gst_tensor_info_validate
gboolean gst_tensor_info_validate(const GstTensorInfo *info)
Check the tensor info is valid.
Definition: nnstreamer_plugin_api_util_impl.c:174
gst_tensor_meta_info_append_header
GstMemory * gst_tensor_meta_info_append_header(GstTensorMetaInfo *meta, GstMemory *mem)
Append header to memory.
Definition: nnstreamer_plugin_api_impl.c:1544
gst_tensor_info_get_size
gsize gst_tensor_info_get_size(const GstTensorInfo *info)
Get data size of single tensor.
Definition: nnstreamer_plugin_api_util_impl.c:156
_get_tensor_caps
static GstCaps * _get_tensor_caps(const GstTensorsConfig *config)
Internal function to get caps for single tensor from config.
Definition: nnstreamer_plugin_api_impl.c:839
gst_tensor_time_sync_mode_string
static const gchar * gst_tensor_time_sync_mode_string[]
Definition: nnstreamer_plugin_api_impl.c:20
gst_tensor_aggregation_get_data
static gst_tensor_aggregation_data_s * gst_tensor_aggregation_get_data(GHashTable *table, const guint32 key)
Internal function to get aggregation data.
Definition: nnstreamer_plugin_api_impl.c:706
failed
Configuring option for tensor decoder failed(option %d=%s)"
gst_tensor_aggregation_data_s
Internal struct to handle aggregation data in hash table.
Definition: nnstreamer_plugin_api_impl.c:657
_tensor_time_sync_data::mode
tensor_time_sync_mode mode
Definition: tensor_common.h:83
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
media_type
enum _nns_media_type media_type
Float16 compiler extension support.
gst_tensor_extra_info_init
static void gst_tensor_extra_info_init(GstTensorExtraInfo *extra, gsize reserved_size)
Initialize GstTensorExtraInfo structure with given memory.
Definition: nnstreamer_plugin_api_impl.c:78
gst_tensor_caps_from_config
GstCaps * gst_tensor_caps_from_config(const GstTensorsConfig *config)
Get tensor caps from tensors config.
Definition: nnstreamer_plugin_api_impl.c:1395
_tensor_time_sync_data::option
gchar * option
Definition: tensor_common.h:84
GST_TENSORS_CAP_DEFAULT
#define GST_TENSORS_CAP_DEFAULT
Caps string for the caps template of static tensor stream.
Definition: tensor_typedef.h:115
gst_tensors_info_get_size
gsize gst_tensors_info_get_size(const GstTensorsInfo *info, gint index)
Get data size of single tensor.
Definition: nnstreamer_plugin_api_util_impl.c:376
_NNS_MEDIA_INVALID
@ _NNS_MEDIA_INVALID
Definition: tensor_typedef.h:181
tensor_common.h
Common header file for NNStreamer, the GStreamer plugin for neural networks.
_NNS_AUDIO
@ _NNS_AUDIO
Definition: tensor_typedef.h:183
gst_tensor_aggregation_clear
void gst_tensor_aggregation_clear(GHashTable *table, const guint32 key)
Clears buffers from adapter.
Definition: nnstreamer_plugin_api_impl.c:763
NNS_MIMETYPE_TENSOR
#define NNS_MIMETYPE_TENSOR
Definition: tensor_typedef.h:59
nns_logw
#define nns_logw
Definition: nnstreamer_log.h:141
GstTensorMetaInfo::format
uint32_t format
Definition: tensor_typedef.h:316
GstTensorsInfo::num_tensors
unsigned int num_tensors
Definition: tensor_typedef.h:275
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_aggregation_clear_all
void gst_tensor_aggregation_clear_all(GHashTable *table)
Clears buffers from all adapters in hash table.
Definition: nnstreamer_plugin_api_impl.c:778
_append_prev_caps
static gboolean _append_prev_caps(const GstTensorsConfig *config)
Internal function to check tensor dimensions to append old caps for backward compatibility (rank 4).
Definition: nnstreamer_plugin_api_impl.c:809
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
ml_logd
#define ml_logd
Definition: nnstreamer_log.h:79
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_tensor_caps_can_intersect
gboolean gst_tensor_caps_can_intersect(GstCaps *caps1, GstCaps *caps2)
Try intersecting @caps1 and @caps2 for tensor stream.
Definition: nnstreamer_plugin_api_impl.c:1142
GstTensorInfo::type
tensor_type type
Definition: tensor_typedef.h:266
GstTensorsConfig::info
GstTensorsInfo info
Definition: tensor_typedef.h:286
gst_tensors_info_parse_dimensions_string
guint gst_tensors_info_parse_dimensions_string(GstTensorsInfo *info, const gchar *dim_string)
Parse the string of dimensions.
Definition: nnstreamer_plugin_api_util_impl.c:532
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
_NNS_TENSOR_FORMAT_END
@ _NNS_TENSOR_FORMAT_END
Definition: tensor_typedef.h:199
_STR_NULL
#define _STR_NULL(str)
If the given string is NULL, print "(NULL)". Copied from GST_STR_NULL
Definition: nnstreamer_plugin_api_util.h:26
tensor_time_sync_mode
tensor_time_sync_mode
time synchronization options
Definition: tensor_common.h:62
gst_tensor_dimension_get_min_rank
guint gst_tensor_dimension_get_min_rank(const tensor_dim dim)
Get the minimum rank of tensor dimension.
Definition: nnstreamer_plugin_api_util_impl.c:1017
gst_tensors_info_get_dimensions_string
gchar * gst_tensors_info_get_dimensions_string(const GstTensorsInfo *info)
Get the string of dimensions in tensors info.
Definition: nnstreamer_plugin_api_util_impl.c:661
gst_tensor_time_sync_get_current_time
gboolean gst_tensor_time_sync_get_current_time(GstCollectPads *collect, tensor_time_sync_data *sync, GstClockTime *current_time, GstBuffer *tensors_buf)
A function call to decide current timestamp among collected pads based on PTS. It will decide current...
Definition: nnstreamer_plugin_api_impl.c:203
GstTensorInfo::dimension
tensor_dim dimension
Definition: tensor_typedef.h:267
GstTensorExtraInfo::magic
uint32_t magic
Definition: nnstreamer_plugin_api_impl.c:41
GstTensorExtraInfo::infos
GstTensorInfo infos[NNS_TENSOR_SIZE_EXTRA_LIMIT]
Definition: nnstreamer_plugin_api_impl.c:45
gst_tensor_time_sync_get_mode
tensor_time_sync_mode gst_tensor_time_sync_get_mode(const gchar *str)
Get the corresponding mode from the string value.
Definition: nnstreamer_plugin_api_impl.c:101
gst_tensor_meta_info_init
void gst_tensor_meta_info_init(GstTensorMetaInfo *meta)
Initialize the tensor meta info structure.
Definition: nnstreamer_plugin_api_util_impl.c:1372
gst_tensors_info_get_rank_dimensions_string
gchar * gst_tensors_info_get_rank_dimensions_string(const GstTensorsInfo *info, const unsigned int rank)
Get the string of dimensions in tensors info and rank count.
Definition: nnstreamer_plugin_api_util_impl.c:676
gst_tensor_aggregation_data_s::adapter
GstAdapter * adapter
Definition: nnstreamer_plugin_api_impl.c:659
gst_tensors_info_parse_types_string
guint gst_tensors_info_parse_types_string(GstTensorsInfo *info, const gchar *type_string)
Parse the string of types.
Definition: nnstreamer_plugin_api_util_impl.c:572
if
if(!gst_tensordec_process_plugin_options(self,(opnum) - 1)) GST_ERROR_OBJECT(self
gst_tensors_config_is_static
#define gst_tensors_config_is_static(c)
Macro to check stream format (static tensors for caps negotiation)
Definition: nnstreamer_plugin_api_util.h:274
GstTensorsInfo::format
tensor_format format
Definition: tensor_typedef.h:278
NNS_MIMETYPE_TENSORS
#define NNS_MIMETYPE_TENSORS
Definition: tensor_typedef.h:60
SYNC_REFRESH
@ SYNC_REFRESH
Definition: tensor_common.h:67
gst_tensor_time_sync_flush
void gst_tensor_time_sync_flush(GstCollectPads *collect)
A function to be called while processing a flushing event. It should clear old buffer and reset pad d...
Definition: nnstreamer_plugin_api_impl.c:263
NNS_TENSOR_SIZE_EXTRA_LIMIT
#define NNS_TENSOR_SIZE_EXTRA_LIMIT
Max number of extra tensors.
Definition: tensor_typedef.h:57
gst_tensor_meta_info_get_header_size
gsize gst_tensor_meta_info_get_header_size(GstTensorMetaInfo *meta)
Get the header size to handle a tensor meta.
Definition: nnstreamer_plugin_api_util_impl.c:1456