Doxygen Book
gsttensor_srciio.c
Go to the documentation of this file.
1 
76 #ifdef HAVE_CONFIG_H
77 #include <config.h>
78 #endif
79 
80 #include <gst/gstinfo.h>
81 #include <gst/gst.h>
82 #include <glib.h>
83 #include <glib/gstdio.h>
84 #include <string.h>
85 #include <endian.h>
86 #include <fcntl.h>
87 #include <unistd.h>
88 #include <errno.h>
89 
90 #include <nnstreamer_util.h>
91 #include "gsttensor_srciio.h"
92 
96 #ifndef DBG
97 #define DBG (!self->silent)
98 #endif
99 
100 GST_DEBUG_CATEGORY_STATIC (gst_tensor_src_iio_debug);
101 #define GST_CAT_DEFAULT gst_tensor_src_iio_debug
102 
106 #define PROCESS_SCANNED_DATA(DTYPE_UNSIGNED, DTYPE_SIGNED) \
107  \
113 static gfloat \
114 gst_tensor_src_iio_process_scanned_data_from_
115  GstTensorSrcIIOChannelProperties *prop, DTYPE_UNSIGNED value_unsigned) { \
116  gfloat value_float; \
117  \
118  g_assert (sizeof (DTYPE_UNSIGNED) == sizeof (DTYPE_SIGNED)); \
119  \
120  value_unsigned >>= prop->shift; \
121  value_unsigned &= prop->mask; \
122  if (prop->is_signed) { \
123  DTYPE_SIGNED value_signed; \
124  guint shift_value; \
125  shift_value = ((guint) (sizeof (DTYPE_UNSIGNED) * 8)) - prop->used_bits; \
126  value_signed = ((DTYPE_SIGNED) (value_unsigned << shift_value)) >> shift_value; \
127  value_float = ((gfloat) value_signed + prop->offset) * prop->scale; \
128  } else { \
129  value_float = ((gfloat) value_unsigned + prop->offset) * prop->scale; \
130  } \
131  return value_float; \
132 }
133 
137 enum
138 {
153 };
154 
158 #define DEFAULT_PROP_BASE_DIRECTORY "/sys/bus/iio/devices"
159 #define DEFAULT_PROP_DEV_DIRECTORY "/dev"
160 
164 #define CHANNELS_ENABLED_AUTO_CHAR "auto"
165 #define CHANNELS_ENABLED_ALL_CHAR "all"
166 #define DEFAULT_OPERATING_CHANNELS_ENABLED CHANNELS_ENABLED_AUTO_CHAR
167 
171 #define MODE_ONE_SHOT "one-shot"
172 #define MODE_CONTINUOUS "continuous"
173 #define DEFAULT_OPERATING_MODE MODE_CONTINUOUS
174 
178 #define DEFAULT_PROP_SILENT TRUE
179 
183 #define DEFAULT_PROP_STRING NULL
184 
188 #define MIN_BUFFER_CAPACITY 1
189 #define MAX_BUFFER_CAPACITY G_MAXUINT
190 #define DEFAULT_BUFFER_CAPACITY 1
191 
196 #define MIN_FREQUENCY 0
197 #define MAX_FREQUENCY G_MAXULONG
198 #define DEFAULT_FREQUENCY 0
199 
203 #define MIN_POLL_TIMEOUT -1
204 #define MAX_POLL_TIMEOUT G_MAXINT
205 #define DEFAULT_POLL_TIMEOUT 10000
206 
210 #define DEFAULT_MERGE_CHANNELS TRUE
211 
215 #define DEFAULT_PROP_DEVICE_NUM -1
216 #define DEFAULT_PROP_TRIGGER_NUM -1
217 
221 #define BLOCKSIZE 1
222 
226 #define DEVICE "device"
227 #define BUFFER "buffer"
228 #define TRIGGER "trigger"
229 #define CHANNELS "scan_elements"
230 #define IIO "iio:"
231 #define TIMESTAMP "timestamp"
232 #define DEVICE_PREFIX IIO DEVICE
233 #define TRIGGER_PREFIX IIO TRIGGER
234 #define CURRENT_TRIGGER "current_trigger"
235 
239 #define EN_SUFFIX "_en"
240 #define INDEX_SUFFIX "_index"
241 #define TYPE_SUFFIX "_type"
242 #define SCALE_SUFFIX "_scale"
243 #define OFFSET_SUFFIX "_offset"
244 
248 #define NAME_FILE "name"
249 #define AVAIL_FREQUENCY_FILE "sampling_frequency_available"
250 #define SAMPLING_FREQUENCY "sampling_frequency"
251 
253 PROCESS_SCANNED_DATA (guint8, gint8);
254 PROCESS_SCANNED_DATA (guint16, gint16);
255 PROCESS_SCANNED_DATA (guint32, gint32);
256 PROCESS_SCANNED_DATA (guint64, gint64);
257 
259 static void gst_tensor_src_iio_set_property (GObject * object, guint prop_id,
260  const GValue * value, GParamSpec * pspec);
261 static void gst_tensor_src_iio_get_property (GObject * object, guint prop_id,
262  GValue * value, GParamSpec * pspec);
263 static void gst_tensor_src_iio_finalize (GObject * object);
264 
266 static gboolean gst_tensor_src_iio_start (GstBaseSrc * src);
267 static gboolean gst_tensor_src_iio_stop (GstBaseSrc * src);
268 static GstStateChangeReturn gst_tensor_src_iio_change_state (GstElement *
269  element, GstStateChange transition);
270 static gboolean gst_tensor_src_iio_event (GstBaseSrc * src, GstEvent * event);
271 static gboolean gst_tensor_src_iio_set_caps (GstBaseSrc * src, GstCaps * caps);
272 static GstCaps *gst_tensor_src_iio_get_caps (GstBaseSrc * src,
273  GstCaps * filter);
274 static GstCaps *gst_tensor_src_iio_fixate (GstBaseSrc * src, GstCaps * caps);
275 static gboolean gst_tensor_src_iio_is_seekable (GstBaseSrc * src);
276 static GstFlowReturn gst_tensor_src_iio_create (GstBaseSrc * src,
277  guint64 offset, guint size, GstBuffer ** buf);
278 static GstFlowReturn gst_tensor_src_iio_fill (GstBaseSrc * src, guint64 offset,
279  guint size, GstBuffer * buf);
280 static void gst_tensor_src_iio_get_times (GstBaseSrc * basesrc,
281  GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
282 
285 #define gst_tensor_src_iio_parent_class parent_class
286 G_DEFINE_TYPE (GstTensorSrcIIO, gst_tensor_src_iio, GST_TYPE_BASE_SRC);
287 
291 static void
293 {
294  GObjectClass *gobject_class;
295  GstElementClass *gstelement_class;
296  GstBaseSrcClass *bsrc_class;
297  GstPadTemplate *pad_template;
298  GstCaps *pad_caps;
299 
300  GST_DEBUG_CATEGORY_INIT (gst_tensor_src_iio_debug, "tensor_src_iio", 0,
301  "Source element to handle Linux Industrial I/O sensors as input");
302 
303  gobject_class = G_OBJECT_CLASS (klass);
304  gstelement_class = GST_ELEMENT_CLASS (klass);
305  bsrc_class = GST_BASE_SRC_CLASS (klass);
306 
308  gobject_class->set_property = gst_tensor_src_iio_set_property;
309  gobject_class->get_property = gst_tensor_src_iio_get_property;
310  gobject_class->finalize = gst_tensor_src_iio_finalize;
311 
312  g_object_class_install_property (gobject_class, PROP_SILENT,
313  g_param_spec_boolean ("silent", "Silent",
314  "Produce verbose output", DEFAULT_PROP_SILENT,
315  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
316 
317  g_object_class_install_property (gobject_class, PROP_MODE,
318  g_param_spec_string ("mode", "Operating mode",
319  "Mode for the device to run in - one-shot or continuous",
320  DEFAULT_OPERATING_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
321 
322  g_object_class_install_property (gobject_class, PROP_BASE_DIRECTORY,
323  g_param_spec_string ("iio-base-dir", "IIO Base Dir",
324  "Base directory for IIO devices", DEFAULT_PROP_BASE_DIRECTORY,
325  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
326 
327  g_object_class_install_property (gobject_class, PROP_DEV_DIRECTORY,
328  g_param_spec_string ("dev-dir", "Dev Dir",
329  "Directory for device files", DEFAULT_PROP_DEV_DIRECTORY,
330  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
331 
332  g_object_class_install_property (gobject_class, PROP_DEVICE,
333  g_param_spec_string ("device", "Device Name",
334  "Name of the device to be opened", DEFAULT_PROP_STRING,
335  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
336 
337  g_object_class_install_property (gobject_class, PROP_DEVICE_NUM,
338  g_param_spec_int ("device-number", "Device Number",
339  "Number (numeric id) of the device to be opened",
340  -1, G_MAXINT, DEFAULT_PROP_DEVICE_NUM, G_PARAM_READWRITE));
341 
342  g_object_class_install_property (gobject_class, PROP_TRIGGER,
343  g_param_spec_string ("trigger", "Trigger Name",
344  "Name of the trigger to be used", DEFAULT_PROP_STRING,
345  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
346 
347  g_object_class_install_property (gobject_class, PROP_TRIGGER_NUM,
348  g_param_spec_int ("trigger-number", "Trigger Number",
349  "Number (numeric id) of the trigger to be opened",
350  -1, G_MAXINT, DEFAULT_PROP_TRIGGER_NUM, G_PARAM_READWRITE));
351 
352  g_object_class_install_property (gobject_class, PROP_CHANNELS,
353  g_param_spec_string ("channels", "Channels to be enabled",
354  "Specify channels to be enabled:"
355  " 1) auto: enable all channels when no channels are enabled automatically,"
356  " 2) all: enable all channels,"
357  " 3) x,y,z: list the idx of the channels to be enabled",
358  DEFAULT_OPERATING_CHANNELS_ENABLED, G_PARAM_READWRITE));
359 
360  g_object_class_install_property (gobject_class, PROP_BUFFER_CAPACITY,
361  g_param_spec_uint ("buffer-capacity", "Buffer Capacity",
362  "Capacity of the data buffer", MIN_BUFFER_CAPACITY,
364  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
365 
366  g_object_class_install_property (gobject_class, PROP_FREQUENCY,
367  g_param_spec_ulong ("frequency", "Frequency",
368  "Operating frequency of the device", MIN_FREQUENCY, MAX_FREQUENCY,
369  DEFAULT_FREQUENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
370 
371  g_object_class_install_property (gobject_class, PROP_MERGE_CHANNELS,
372  g_param_spec_boolean ("merge-channels-data", "Merge Channels Data",
373  "Merge the data of channels into single tensor",
374  DEFAULT_MERGE_CHANNELS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
375 
376  g_object_class_install_property (gobject_class, PROP_POLL_TIMEOUT,
377  g_param_spec_int ("poll-timeout", "Poll Timeout",
378  "Timeout for polling in milliseconds", MIN_POLL_TIMEOUT,
379  MAX_POLL_TIMEOUT, DEFAULT_POLL_TIMEOUT, G_PARAM_READWRITE));
380 
381  gst_element_class_set_static_metadata (gstelement_class,
382  "TensorSrcIIO",
383  "Source/Tensor/Device",
384  "Src element to support linux IIO",
385  "Parichay Kapoor <pk.kapoor@samsung.com>");
386 
388  pad_caps = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT "; "
390  pad_template = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
391  pad_caps);
392  gst_element_class_add_pad_template (gstelement_class, pad_template);
393  gst_caps_unref (pad_caps);
394 
395  gstelement_class->change_state =
396  GST_DEBUG_FUNCPTR (gst_tensor_src_iio_change_state);
397 
399  bsrc_class->start = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_start);
400  bsrc_class->stop = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_stop);
401  bsrc_class->event = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_event);
402  bsrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_set_caps);
403  bsrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_get_caps);
404  bsrc_class->fixate = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_fixate);
405  bsrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_is_seekable);
406  bsrc_class->create = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_create);
407  bsrc_class->fill = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_fill);
408  bsrc_class->get_times = GST_DEBUG_FUNCPTR (gst_tensor_src_iio_get_times);
409 }
410 
415 static void
417 {
420  g_free (prop->name);
422  g_free (prop->base_dir);
423  g_free (prop->base_file);
424  g_free (prop);
425 }
426 
431 static void
433  prop)
434 {
435  prop->name = NULL;
436  prop->base_dir = NULL;
437  prop->id = -1;
438 }
439 
443 static void
445 {
447  self->configured = FALSE;
448  self->channels = NULL;
449  self->custom_channel_table = NULL;
450  self->mode = g_strdup (DEFAULT_OPERATING_MODE);
451  self->channels_enabled = CHANNELS_ENABLED_AUTO;
452  self->base_dir = g_strdup (DEFAULT_PROP_BASE_DIRECTORY);
453  self->dev_dir = g_strdup (DEFAULT_PROP_DEV_DIRECTORY);
456  self->silent = DEFAULT_PROP_SILENT;
457  self->buffer_capacity = DEFAULT_BUFFER_CAPACITY;
458  self->sampling_frequency = DEFAULT_FREQUENCY;
459  self->merge_channels_data = DEFAULT_MERGE_CHANNELS;
460  self->is_tensor = FALSE;
461  self->tensors_config = NULL;
462  self->default_sampling_frequency = 0;
463  self->default_buffer_capacity = 0;
464  self->default_trigger = NULL;
465  self->poll_timeout = DEFAULT_POLL_TIMEOUT;
466 
471  gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
473  gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
475  gst_base_src_set_do_timestamp (GST_BASE_SRC (self), TRUE);
480  gst_base_src_set_async (GST_BASE_SRC (self), TRUE);
481 }
482 
495 static gint
497  guint dir)
498 {
499  guint info_idx, base_idx;
500  gint dim_idx;
501  gboolean mismatch = FALSE, dim_avail = FALSE;
502  gint merge_dim = -1;
503 
505  g_return_val_if_fail (size > 0, 0);
506  base_idx = 0;
507 
509  for (dim_idx = 0; dim_idx < NNS_TENSOR_RANK_LIMIT; dim_idx++) {
510  if (info[base_idx].dimension[dim_idx] == 1) {
511  dim_avail = TRUE;
512  }
513  }
514 
516  for (info_idx = 0; info_idx < size; info_idx++) {
517  if (!gst_tensor_info_is_equal (info + base_idx, info + info_idx)) {
518  mismatch = TRUE;
519  break;
520  }
521  }
522 
524  if (mismatch || !dim_avail) {
525  if (size > NNS_TENSOR_SIZE_LIMIT) {
526  return -1;
527  } else {
528  return size;
529  }
530  }
531 
537  if (dir == 0) {
538  for (dim_idx = 0; dim_idx < NNS_TENSOR_RANK_LIMIT; dim_idx++) {
539  if (info[base_idx].dimension[dim_idx] == 1) {
540  merge_dim = dim_idx;
541  break;
542  }
543  }
544  } else if (dir == 1) {
545  for (dim_idx = NNS_TENSOR_RANK_LIMIT - 1; dim_idx >= 0; dim_idx--) {
546  if (info[base_idx].dimension[dim_idx] == 1) {
547  merge_dim = dim_idx;
548  break;
549  }
550  }
551  } else if (dir == 2) {
552  for (dim_idx = NNS_TENSOR_RANK_LIMIT - 1; dim_idx >= 0; dim_idx--) {
553  if (info[base_idx].dimension[dim_idx] != 1) {
554  merge_dim = dim_idx + 1;
555  break;
556  }
557  }
558  } else {
559  return -1;
560  }
561 
563  if (merge_dim >= NNS_TENSOR_RANK_LIMIT || merge_dim < 0) {
564  return size;
565  }
566 
568  info[0].dimension[merge_dim] = size;
569  return 1;
570 }
571 
580 static gint
581 gst_tensor_src_iio_get_id_by_name (const gchar * dir_name, const gchar * name,
582  const gchar * prefix)
583 {
584  DIR *dptr = NULL;
585  GError *error = NULL;
586  struct dirent *dir_entry;
587  gchar *filename = NULL;
588  gint id = -1;
589  gchar *file_contents = NULL;
590  gint ret = -1;
591 
592  if (!g_file_test (dir_name, G_FILE_TEST_IS_DIR)) {
593  GST_ERROR ("No channels available.");
594  return ret;
595  }
596  dptr = opendir (dir_name);
597  if (G_UNLIKELY (NULL == dptr)) {
598  GST_ERROR ("Error in opening directory %s.\n", dir_name);
599  return ret;
600  }
601 
602  while ((dir_entry = readdir (dptr)) != NULL) {
604  if (g_str_has_prefix (dir_entry->d_name, prefix) &&
605  g_ascii_isdigit (dir_entry->d_name[strlen (prefix)])) {
606 
607  id = (gint) g_ascii_strtoll (dir_entry->d_name + strlen (prefix), NULL,
608  10);
609  filename =
610  g_build_filename (dir_name, dir_entry->d_name, NAME_FILE, NULL);
611 
612  if (!g_file_get_contents (filename, &file_contents, NULL, &error)) {
613  GST_ERROR ("Unable to read %s, error: %s.\n", filename, error->message);
614  g_error_free (error);
615  goto error_free_filename;
616  }
617  g_free (filename);
618 
619  if (g_strcmp0 (file_contents, name) == 0) {
620  ret = id;
621  g_free (file_contents);
622  break;
623  }
624  g_free (file_contents);
625  }
626  }
627 
628  closedir (dptr);
629  return ret;
630 
631 error_free_filename:
632  g_free (filename);
633  closedir (dptr);
634  return ret;
635 }
636 
644 static gchar *
645 gst_tensor_src_iio_get_name_by_id (const gchar * dir_name, const gint id,
646  const gchar * prefix)
647 {
648  GError *error = NULL;
649  gchar *filename = NULL;
650  gchar *dev_dirname = NULL;
651  gchar *file_contents = NULL;
652 
653  dev_dirname = g_strdup_printf ("%s%d", prefix, id);
654  filename = g_build_filename (dir_name, dev_dirname, NAME_FILE, NULL);
655  g_free (dev_dirname);
656 
657  if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
658  GST_ERROR ("No device available with id %d.", id);
659  goto exit_free_filename;
660  }
661 
662  if (!g_file_get_contents (filename, &file_contents, NULL, &error)) {
663  GST_ERROR ("Unable to read %s, error: %s.\n", filename, error->message);
664  g_error_free (error);
665  goto exit_free_filename;
666  }
667 
668 exit_free_filename:
669  g_free (filename);
670  return file_contents;
671 }
672 
681 static gboolean
682 gst_tensor_src_iio_get_float_from_file (const gchar * dirname,
683  const gchar * name, const gchar * suffix, gfloat * value)
684 {
685  gchar *filename, *filepath, *file_contents = NULL;
686 
687  errno = 0;
688  filename = g_strdup_printf ("%s%s", name, suffix);
689  filepath = g_build_filename (dirname, filename, NULL);
690 
691  if (!g_file_get_contents (filepath, &file_contents, NULL, NULL)) {
692  GST_INFO ("Unable to retrieve data from file %s.", filename);
693  } else {
694  *value = (gfloat) g_ascii_strtod (file_contents, NULL);
695  if (errno != 0) {
696  GST_ERROR ("Error in parsing float.");
697  goto failure;
698  }
699  g_free (file_contents);
700  }
701  g_free (filename);
702  g_free (filepath);
703 
704  return TRUE;
705 
706 failure:
707  g_free (file_contents);
708  g_free (filename);
709  g_free (filepath);
710  return FALSE;
711 }
712 
722 static gboolean
724  const gchar * contents)
725 {
726  gchar endianchar = '\0', signchar = '\0';
727  gchar *start, *end;
728  guint base = 10;
729  errno = 0;
730 
732  endianchar = contents[0];
733  if (endianchar == 'b') {
734  prop->big_endian = TRUE;
735  } else if (endianchar == 'l') {
736  prop->big_endian = FALSE;
737  } else {
738  goto exit_fail;
739  }
740 
742  g_return_val_if_fail (contents[1] == 'e', FALSE);
743  g_return_val_if_fail (contents[2] == ':', FALSE);
744 
746  signchar = contents[3];
747  if (signchar == 's') {
748  prop->is_signed = TRUE;
749  } else if (signchar == 'u') {
750  prop->is_signed = FALSE;
751  } else {
752  goto exit_fail;
753  }
754 
756  start = (gchar *) contents + 4;
757  prop->used_bits = (guint) g_ascii_strtoull (start, &end, base);
758  if (errno != 0) {
759  goto exit_fail;
760  }
762  g_return_val_if_fail (end[0] == '/', FALSE);
763  prop->mask = G_MAXUINT64 >> (64 - prop->used_bits);
764 
766  start = &end[1];
767  prop->storage_bits = (guint) g_ascii_strtoull (start, &end, base);
768  if (errno != 0) {
769  goto exit_fail;
770  }
772  g_return_val_if_fail (end[0] == '>', FALSE);
773  g_return_val_if_fail (end[1] == '>', FALSE);
774  g_return_val_if_fail (prop->storage_bits >= prop->used_bits, FALSE);
775 
776  if (prop->storage_bits > 0) {
777  prop->storage_bytes = ((prop->storage_bits - 1) >> 3) + 1;
778  g_return_val_if_fail (prop->storage_bytes <= 8, FALSE);
779  } else {
780  GST_WARNING ("Storage bits are 0 for channel %s.", prop->name);
781  prop->storage_bytes = 0;
782  }
783 
784  start = &end[2];
785  prop->shift = (guint) g_ascii_strtoull (start, &end, base);
786  if (errno != 0) {
787  goto exit_fail;
788  }
789  g_return_val_if_fail (prop->storage_bits > prop->shift, FALSE);
790 
791  return TRUE;
792 
793 exit_fail:
794  return FALSE;
795 }
796 
803 static gchar *
804 gst_tensor_src_iio_get_generic_name (const gchar * channel_name)
805 {
806  gsize digit_len = 1;
807  gchar *generic_name;
808  gsize channel_name_len = strlen (channel_name);
809 
810  while (g_ascii_isdigit (channel_name[channel_name_len - digit_len])) {
811  digit_len++;
812  }
813  generic_name = g_strndup (channel_name, channel_name_len - digit_len + 1);
814 
815  return generic_name;
816 }
817 
826 static gint
827 gst_tensor_channel_list_sort_cmp (gconstpointer a, gconstpointer b)
828 {
829  const GstTensorSrcIIOChannelProperties *a_ch = a;
830  const GstTensorSrcIIOChannelProperties *b_ch = b;
831  gint compare_result = a_ch->index - b_ch->index;
832  return compare_result;
833 }
834 
840 static void
841 gst_tensor_channel_list_filter_enabled (gpointer data, gpointer user_data)
842 {
844  GList **list_addr;
845  GList *list;
846 
848  list_addr = (GList **) user_data;
849  list = *list_addr;
850 
851  if (!channel->enabled) {
852  *list_addr = g_list_remove (list, data);
854  }
855 }
856 
864 static gint
866  const gchar * dir_name)
867 {
868  DIR *dptr = NULL;
869  GError *error = NULL;
870  const struct dirent *dir_entry;
871  gchar *filename = NULL;
872  gchar *file_contents = NULL;
873  gint ret = -1;
874  guint value;
875  guint num_channels_enabled = 0;
876  gboolean generic_val, specific_val;
877  gchar *generic_type_filename;
878  GstTensorSrcIIOChannelProperties *channel_prop;
879 
880  if (!g_file_test (dir_name, G_FILE_TEST_IS_DIR)) {
881  GST_ERROR_OBJECT (self, "No channels available.");
882  return ret;
883  }
884  dptr = opendir (dir_name);
885  if (G_UNLIKELY (NULL == dptr)) {
886  GST_ERROR_OBJECT (self, "Error in opening directory %s.\n", dir_name);
887  return ret;
888  }
889 
890  while ((dir_entry = readdir (dptr)) != NULL) {
892  if (g_str_has_suffix (dir_entry->d_name, EN_SUFFIX)) {
894  if (g_str_has_prefix (dir_entry->d_name, TIMESTAMP)) {
895  continue;
896  }
897 
898  channel_prop = g_new0 (GstTensorSrcIIOChannelProperties, 1);
899  if (channel_prop == NULL) {
900  GST_ERROR_OBJECT (self, "Failed to allocate for channel property.");
901  goto error_cleanup_list;
902  }
903 
904  self->channels = g_list_prepend (self->channels, channel_prop);
905 
907  channel_prop->name = g_strndup (dir_entry->d_name,
908  strlen (dir_entry->d_name) - strlen (EN_SUFFIX));
909  channel_prop->base_dir = g_strdup (dir_name);
910  channel_prop->base_file =
911  g_build_filename (dir_name, channel_prop->name, NULL);
912  channel_prop->generic_name =
914  silent_debug (self, "Generic name = %s", channel_prop->generic_name);
915 
917  filename = g_strdup_printf ("%s%s", channel_prop->base_file, EN_SUFFIX);
918  if (!g_file_get_contents (filename, &file_contents, NULL, &error)) {
919  GST_ERROR_OBJECT (self, "Unable to read %s, error: %s.\n", filename,
920  error->message);
921  goto error_free_filename;
922  }
923  g_free (filename);
924 
925  value = (guint) g_ascii_strtoull (file_contents, NULL, 10);
926  g_free (file_contents);
927  if (value == 1) {
928  channel_prop->enabled = TRUE;
929  channel_prop->pre_enabled = TRUE;
930  num_channels_enabled += 1;
931  } else if (value == 0) {
932  channel_prop->enabled = FALSE;
933  channel_prop->pre_enabled = FALSE;
934  } else {
935  GST_ERROR_OBJECT
936  (self,
937  "Enable bit %u (out of range) in current state of channel %s.\n",
938  value, channel_prop->name);
939  goto error_cleanup_list;
940  }
941 
943  filename =
944  g_strdup_printf ("%s%s", channel_prop->base_file, INDEX_SUFFIX);
945  if (!g_file_get_contents (filename, &file_contents, NULL, &error)) {
946  GST_ERROR_OBJECT (self, "Unable to read %s, error: %s.\n", filename,
947  error->message);
948  goto error_free_filename;
949  }
950  g_free (filename);
951 
952  value = (guint) g_ascii_strtoull (file_contents, NULL, 10);
953  g_free (file_contents);
954  channel_prop->index = value;
955 
957  filename = g_strdup_printf ("%s%s", channel_prop->base_file, TYPE_SUFFIX);
958  if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
960  g_free (filename);
961  generic_type_filename =
962  g_strdup_printf ("%s%s", channel_prop->generic_name, TYPE_SUFFIX);
963  filename =
964  g_build_filename (channel_prop->base_dir, generic_type_filename,
965  NULL);
966  g_free (generic_type_filename);
967  }
968  if (!g_file_get_contents (filename, &file_contents, NULL, &error)) {
969  GST_ERROR_OBJECT (self, "Unable to read %s, error: %s.\n", filename,
970  error->message);
971  goto error_free_filename;
972  }
973  g_free (filename);
974 
975  if (!gst_tensor_src_iio_set_channel_type (channel_prop, file_contents)) {
976  GST_ERROR_OBJECT (self,
977  "Error while setting up channel type for channel %s.\n",
978  channel_prop->name);
979  g_free (file_contents);
980  goto error_cleanup_list;
981  }
982  g_free (file_contents);
983 
985  channel_prop->scale = 1.0;
986 
987  specific_val =
988  gst_tensor_src_iio_get_float_from_file (self->device.base_dir,
989  channel_prop->name, SCALE_SUFFIX, &channel_prop->scale);
990  generic_val =
991  gst_tensor_src_iio_get_float_from_file (self->device.base_dir,
992  channel_prop->generic_name, SCALE_SUFFIX, &channel_prop->scale);
993  if (!specific_val || !generic_val) {
994  goto error_cleanup_list;
995  }
996 
998  channel_prop->offset = 0.0;
999 
1000  specific_val =
1001  gst_tensor_src_iio_get_float_from_file (self->device.base_dir,
1002  channel_prop->name, OFFSET_SUFFIX, &channel_prop->offset);
1003  generic_val =
1004  gst_tensor_src_iio_get_float_from_file (self->device.base_dir,
1005  channel_prop->generic_name, OFFSET_SUFFIX, &channel_prop->offset);
1006  if (!specific_val || !generic_val) {
1007  goto error_cleanup_list;
1008  }
1009  }
1010  }
1011 
1013  self->channels =
1014  g_list_sort (self->channels, gst_tensor_channel_list_sort_cmp);
1015  ret = num_channels_enabled;
1016 
1017  closedir (dptr);
1018  return ret;
1019 
1020 error_free_filename:
1021  g_error_free (error);
1022  g_free (filename);
1023 
1024 error_cleanup_list:
1025  g_list_free_full (self->channels, gst_tensor_src_iio_channel_properties_free);
1026  self->channels = NULL;
1027 
1028  closedir (dptr);
1029  return ret;
1030 }
1031 
1040 static gint64
1041 gst_tensor_src_iio_get_available_frequency (const gchar * base_dir,
1042  const guint64 frequency)
1043 {
1044  GError *error = NULL;
1045  gchar *filename = NULL;
1046  gchar *file_contents = NULL;
1047  gint i = 0;
1048  guint64 val = 0;
1049  gint64 ret = 0;
1050  gchar **freq_list = NULL;
1051  gint num = 0;
1052 
1054  filename = g_build_filename (base_dir, AVAIL_FREQUENCY_FILE, NULL);
1055  if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
1056  GST_WARNING ("Sampling frequency file does not exist for the file %s.\n",
1057  base_dir);
1058  goto del_filename;
1059  }
1060  if (!g_file_get_contents (filename, &file_contents, NULL, &error)) {
1061  GST_ERROR ("Unable to read sampling frequency for device %s.\n", base_dir);
1062  g_error_free (error);
1063  ret = -1;
1064  goto del_filename;
1065  }
1066 
1067  freq_list = g_strsplit (file_contents, " ", -1);
1068  num = g_strv_length (freq_list);
1069  if (num == 0) {
1070  GST_ERROR ("No sampling frequencies for device %s.\n", base_dir);
1071  ret = -1;
1072  goto del_freq_list;
1073  }
1078  if (frequency == 0) {
1079  ret = g_ascii_strtoll (freq_list[0], NULL, 10);
1080  } else {
1081  for (i = 0; i < num; i++) {
1082  val = g_ascii_strtoull (freq_list[i], NULL, 10);
1083  if (frequency == val) {
1084  ret = frequency;
1085  break;
1086  }
1087  }
1088  }
1089 
1090 del_freq_list:
1091  g_strfreev (freq_list);
1092 
1093 del_filename:
1094  g_free (file_contents);
1095  g_free (filename);
1096  return ret;
1097 }
1102 static void
1103 gst_tensor_src_iio_set_property (GObject * object, guint prop_id,
1104  const GValue * value, GParamSpec * pspec)
1105 {
1106  GstTensorSrcIIO *self;
1107  GstStateChangeReturn ret;
1108  GstState state;
1109 
1110  self = GST_TENSOR_SRC_IIO (object);
1111 
1117  ret = gst_element_get_state (GST_ELEMENT (self), &state, NULL,
1118  GST_CLOCK_TIME_NONE);
1119  if (ret == GST_STATE_CHANGE_FAILURE || ret == GST_STATE_CHANGE_ASYNC
1120  || state == GST_STATE_PLAYING || state == GST_STATE_PAUSED) {
1121  GST_ERROR_OBJECT (self, "Can only set property in NULL or READY state.");
1122  return;
1123  }
1124 
1125  switch (prop_id) {
1126  case PROP_SILENT:
1127  self->silent = g_value_get_boolean (value);
1128  break;
1129 
1130  case PROP_BASE_DIRECTORY:
1131  {
1132  const gchar *base_dir = g_value_get_string (value);
1133 
1134  if (g_path_is_absolute (base_dir)) {
1135  g_free (self->base_dir);
1136  self->base_dir = g_strdup (base_dir);
1137  } else {
1138  GST_ERROR_OBJECT (self, "%s is not an absolute path.", base_dir);
1139  }
1140 
1141  break;
1142  }
1143  case PROP_DEV_DIRECTORY:
1144  {
1145  const gchar *dev_dir = g_value_get_string (value);
1146 
1147  if (g_path_is_absolute (dev_dir)) {
1148  g_free (self->dev_dir);
1149  self->dev_dir = g_strdup (dev_dir);
1150  } else {
1151  GST_ERROR_OBJECT (self, "%s is not an absolute path.", dev_dir);
1152  }
1153 
1154  break;
1155  }
1156  case PROP_MODE:
1157  {
1158  if (self->mode != NULL) {
1159  g_free (self->mode);
1160  }
1161  self->mode = g_value_dup_string (value);
1162  break;
1163  }
1164 
1165  case PROP_DEVICE:
1166  {
1167  if (self->device.name != NULL) {
1168  g_free (self->device.name);
1169  }
1170  self->device.name = g_value_dup_string (value);
1171  break;
1172  }
1173 
1174  case PROP_DEVICE_NUM:
1175  self->device.id = g_value_get_int (value);
1176  break;
1177 
1178  case PROP_TRIGGER:
1179  {
1180  if (self->trigger.name != NULL) {
1181  g_free (self->trigger.name);
1182  }
1183  self->trigger.name = g_value_dup_string (value);
1184  break;
1185  }
1186 
1187  case PROP_TRIGGER_NUM:
1188  self->trigger.id = g_value_get_int (value);
1189  break;
1190 
1191  case PROP_CHANNELS:
1192  {
1193  const gchar *param = g_value_get_string (value);
1194  if (g_ascii_strncasecmp (param, CHANNELS_ENABLED_ALL_CHAR,
1195  strlen (CHANNELS_ENABLED_ALL_CHAR)) == 0) {
1196  self->channels_enabled = CHANNELS_ENABLED_ALL;
1197  } else if (g_ascii_strncasecmp (param, CHANNELS_ENABLED_AUTO_CHAR,
1198  strlen (CHANNELS_ENABLED_AUTO_CHAR)) == 0) {
1199  self->channels_enabled = CHANNELS_ENABLED_AUTO;
1200  } else {
1201  gint i, num;
1202  gint64 val;
1203  gchar **strv;
1204  gchar *endptr = NULL;
1205  gboolean status = TRUE;
1206 
1211  self->custom_channel_table =
1212  g_hash_table_new (g_direct_hash, g_direct_equal);
1213  strv = g_strsplit_set (param, ",;", -1);
1214  num = g_strv_length (strv);
1215  for (i = 0; i < num; i++) {
1216  val = g_ascii_strtoll (strv[i], &endptr, 10);
1217  if (errno == ERANGE || errno == EINVAL || (endptr == strv[i]
1218  && val == 0)) {
1219  GST_ERROR_OBJECT (self,
1220  "Cannot parse received custom channels %s. The property values for CHANNELS are ignored.",
1221  param);
1222  g_hash_table_destroy (self->custom_channel_table);
1223  self->custom_channel_table = NULL;
1224  status = FALSE;
1225  break;
1226  }
1227  if (!g_hash_table_insert (self->custom_channel_table,
1228  GINT_TO_POINTER (val), NULL)) {
1230  ml_logw
1231  ("tensor-src-iio's CHANNELS property value has a duplicated entry, '%s', which is registered only once.\n",
1232  strv[i]);
1233  }
1234  }
1235  if (status)
1236  self->channels_enabled = CHANNELS_ENABLED_CUSTOM;
1237  g_strfreev (strv);
1238  break;
1239  }
1240  break;
1241  }
1242 
1243  case PROP_BUFFER_CAPACITY:
1244  self->buffer_capacity = g_value_get_uint (value);
1245  break;
1246 
1247  case PROP_FREQUENCY:
1248  self->sampling_frequency = (guint64) g_value_get_ulong (value);
1249  break;
1250 
1251  case PROP_MERGE_CHANNELS:
1252  self->merge_channels_data = g_value_get_boolean (value);
1253  break;
1254 
1255  case PROP_POLL_TIMEOUT:
1256  self->poll_timeout = g_value_get_int (value);
1257  break;
1258 
1259  default:
1260  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1261  break;
1262  }
1263 }
1268 static void
1269 gst_tensor_src_iio_get_property (GObject * object, guint prop_id,
1270  GValue * value, GParamSpec * pspec)
1271 {
1272  GstTensorSrcIIO *self;
1273  self = GST_TENSOR_SRC_IIO (object);
1274 
1275  switch (prop_id) {
1276  case PROP_SILENT:
1277  g_value_set_boolean (value, self->silent);
1278  break;
1279 
1280  case PROP_MODE:
1281  g_value_set_string (value, self->mode);
1282  break;
1283 
1284  case PROP_BASE_DIRECTORY:
1285  g_value_set_string (value, self->base_dir);
1286  break;
1287 
1288  case PROP_DEV_DIRECTORY:
1289  g_value_set_string (value, self->dev_dir);
1290  break;
1291 
1292  case PROP_DEVICE:
1293  g_value_set_string (value, self->device.name);
1294  break;
1295 
1296  case PROP_DEVICE_NUM:
1297  g_value_set_int (value, self->device.id);
1298  break;
1299 
1300  case PROP_TRIGGER:
1301  g_value_set_string (value, self->trigger.name);
1302  break;
1303 
1304  case PROP_TRIGGER_NUM:
1305  g_value_set_int (value, self->trigger.id);
1306  break;
1307 
1308  case PROP_CHANNELS:
1309  {
1310  if (self->channels_enabled == CHANNELS_ENABLED_ALL) {
1312  } else if (self->channels_enabled == CHANNELS_ENABLED_AUTO) {
1314  } else {
1315  GHashTableIter iter;
1316  gpointer key;
1317  gchar *p = NULL;
1318  GPtrArray *arr = g_ptr_array_new ();
1319  gchar **strings;
1320 
1321  g_hash_table_iter_init (&iter, self->custom_channel_table);
1322  while (g_hash_table_iter_next (&iter, &key, NULL)) {
1323  g_ptr_array_add (arr, g_strdup_printf ("%u", GPOINTER_TO_INT (key)));
1324  }
1325  g_ptr_array_add (arr, NULL);
1326 
1327  strings = (gchar **) g_ptr_array_free (arr, FALSE);
1328  p = g_strjoinv (",", strings);
1329  g_strfreev (strings);
1330  g_value_take_string (value, p);
1331  break;
1332  }
1333  break;
1334  }
1335 
1336  case PROP_BUFFER_CAPACITY:
1337  g_value_set_uint (value, self->buffer_capacity);
1338  break;
1339 
1340  case PROP_FREQUENCY:
1342  g_value_set_ulong (value, (gulong) self->sampling_frequency);
1343  break;
1344 
1345  case PROP_MERGE_CHANNELS:
1346  g_value_set_boolean (value, self->merge_channels_data);
1347  break;
1348 
1349  case PROP_POLL_TIMEOUT:
1350  g_value_set_int (value, self->poll_timeout);
1351  break;
1352 
1353  default:
1354  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1355  break;
1356  }
1357 }
1362 static void
1363 gst_tensor_src_iio_finalize (GObject * object)
1364 {
1365  GstTensorSrcIIO *self;
1366  self = GST_TENSOR_SRC_IIO (object);
1367 
1368  g_free (self->mode);
1369  g_free (self->device.name);
1370  g_free (self->trigger.name);
1371  g_free (self->base_dir);
1372  g_free (self->dev_dir);
1373  if (self->custom_channel_table) {
1374  g_hash_table_destroy (self->custom_channel_table);
1375  }
1376 
1377  G_OBJECT_CLASS (parent_class)->finalize (object);
1378 }
1379 
1388 static gboolean
1389 gst_tensor_write_sysfs_string (GstTensorSrcIIO * self, const gchar * file,
1390  const gchar * base_dir, const gchar * contents)
1391 {
1392  gchar *filename = NULL;
1393  gboolean ret = FALSE;
1394  guint bytes_printed = 0;
1395  FILE *fd = NULL;
1396  GError *error = NULL;
1397 
1398  filename = g_build_filename (base_dir, file, NULL);
1399  fd = g_fopen (filename, "w");
1400  if (fd == NULL) {
1401  GST_ERROR_OBJECT (self, "Unable to open file to write %s.\n", filename);
1402  goto error_free_filename;
1403  }
1404 
1405  bytes_printed = fprintf (fd, "%s", contents);
1406  if (bytes_printed != strlen (contents)) {
1407  GST_ERROR_OBJECT (self, "Unable to write to file %s.\n", filename);
1408  goto error_close_file;
1409  }
1410  if (fclose (fd) != 0) {
1411  GST_ERROR_OBJECT (self, "Unable to close file %s after write.\n", filename);
1412  goto error_free_filename;
1413  }
1414  ret = TRUE;
1415 
1416  if (DBG) {
1417  gchar *file_contents = NULL;
1418  ret = FALSE;
1419  if (!g_file_get_contents (filename, &file_contents, NULL, &error)) {
1420  GST_ERROR_OBJECT (self, "Unable to read file %s with error %s.\n",
1421  filename, error->message);
1422  g_error_free (error);
1423  goto error_free_filename;
1424  } else {
1425  if (g_strcmp0 (contents, file_contents) == 0) {
1426  ret = TRUE;
1427  }
1428  g_free (file_contents);
1429  }
1430  }
1431 
1432  g_free (filename);
1433  return ret;
1434 
1435 error_close_file:
1436  if (fclose (fd) != 0) {
1437  GST_ERROR_OBJECT (self, "Unable to close file %s.\n", filename);
1438  }
1439 
1440 error_free_filename:
1441  g_free (filename);
1442  return ret;
1443 }
1444 
1453 static gboolean
1454 gst_tensor_write_sysfs_int (GstTensorSrcIIO * self, const gchar * file,
1455  const gchar * base_dir, const gint contents)
1456 {
1457  gchar *contents_char = NULL;
1458  gboolean ret;
1459 
1460  contents_char = g_strdup_printf ("%d", contents);
1461  ret = gst_tensor_write_sysfs_string (self, file, base_dir, contents_char);
1462 
1463  g_free (contents_char);
1464  return ret;
1465 }
1466 
1473 static gboolean
1474 gst_tensor_set_all_channels (GstTensorSrcIIO * self, const gint contents)
1475 {
1476  GList *ch_list;
1477  gchar *filename = NULL;
1478  GstTensorSrcIIOChannelProperties *channel_prop = NULL;
1479  gboolean ret = TRUE;
1480 
1481  for (ch_list = self->channels; ch_list != NULL; ch_list = ch_list->next) {
1482  channel_prop = (GstTensorSrcIIOChannelProperties *) ch_list->data;
1483  filename = g_strdup_printf ("%s%s", channel_prop->name, EN_SUFFIX);
1484  if (gst_tensor_write_sysfs_int (self, filename, channel_prop->base_dir,
1485  contents)) {
1486  channel_prop->enabled = TRUE;
1487  } else {
1488  ret = FALSE;
1489  }
1490  g_free (filename);
1491  }
1492 
1493  return ret;
1494 }
1495 
1503 static guint
1504 gst_tensor_get_size_from_channels (GList * channels)
1505 {
1506  guint size_bytes = 0;
1507  guint remain = 0;
1508  GList *list;
1509  GstTensorSrcIIOChannelProperties *channel_prop = NULL;
1510 
1511  for (list = channels; list != NULL; list = list->next) {
1512  channel_prop = (GstTensorSrcIIOChannelProperties *) list->data;
1513  remain = size_bytes % channel_prop->storage_bytes;
1514  if (remain == 0) {
1515  channel_prop->location = size_bytes;
1516  } else {
1517  channel_prop->location =
1518  size_bytes - remain + channel_prop->storage_bytes;
1519  }
1520  size_bytes = channel_prop->location + channel_prop->storage_bytes;
1521  }
1522 
1523  return size_bytes;
1524 }
1525 
1531 static gboolean
1533 {
1534  GList *list;
1535  GstTensorSrcIIOChannelProperties *channel_prop;
1536  gint tensor_info_merged_size;
1537  guint info_idx = 0;
1538  GstTensorInfo *info, *dest;
1539  GstTensorsConfig *config;
1540 
1545  info = g_new0 (GstTensorInfo, tensor_src_iio->num_channels_enabled);
1546  if (info == NULL) {
1547  GST_ERROR_OBJECT (tensor_src_iio, "Failed to allocate caps config data.");
1548  return FALSE;
1549  }
1550 
1552  for (list = tensor_src_iio->channels; list != NULL; list = list->next) {
1553  gst_tensor_info_init (&info[info_idx]);
1554 
1555  channel_prop = (GstTensorSrcIIOChannelProperties *) list->data;
1556  if (!channel_prop->enabled)
1557  continue;
1558  info[info_idx].name = channel_prop->name;
1559  info[info_idx].type = _NNS_FLOAT32;
1560  info[info_idx].dimension[0] = 1;
1561  info[info_idx].dimension[1] = tensor_src_iio->buffer_capacity;
1562  info_idx += 1;
1563  }
1564 
1565  if (info_idx != tensor_src_iio->num_channels_enabled) {
1566  GST_ERROR_OBJECT (tensor_src_iio, "The number of channel is different.");
1567  goto error_ret;
1568  }
1569 
1571  tensor_info_merged_size = tensor_src_iio->num_channels_enabled;
1572  if (tensor_src_iio->merge_channels_data) {
1573  tensor_info_merged_size =
1575  tensor_src_iio->num_channels_enabled, 0);
1576  }
1577 
1579  if (tensor_info_merged_size < 0) {
1580  GST_ERROR_OBJECT (tensor_src_iio, "Mismatch while merging tensor");
1581  goto error_ret;
1582  } else if (tensor_info_merged_size == 0) {
1583  GST_ERROR_OBJECT (tensor_src_iio, "No info to be merged");
1584  goto error_ret;
1585  } else if (tensor_info_merged_size > NNS_TENSOR_SIZE_LIMIT) {
1586  GST_ERROR_OBJECT (tensor_src_iio,
1587  "Number of tensors required %u for data exceed the max limit",
1588  tensor_info_merged_size);
1589  goto error_ret;
1590  }
1591 
1593  tensor_src_iio->is_tensor = (tensor_info_merged_size == 1);
1594  config = g_new (GstTensorsConfig, 1);
1595  if (config == NULL) {
1596  goto error_ret;
1597  }
1598  gst_tensors_config_init (config);
1599  for (info_idx = 0; info_idx < (guint) tensor_info_merged_size; info_idx++) {
1600  dest = gst_tensors_info_get_nth_info (&config->info, info_idx);
1601  gst_tensor_info_copy (dest, &info[info_idx]);
1602  }
1603 
1608  config->rate_n = tensor_src_iio->sampling_frequency;
1609  config->rate_d = tensor_src_iio->buffer_capacity;
1610  config->info.num_tensors = tensor_info_merged_size;
1611 
1612  tensor_src_iio->tensors_config = config;
1613 
1614  g_free (info);
1615  return TRUE;
1616 
1617 error_ret:
1618  g_free (info);
1619  return FALSE;
1620 }
1621 
1627 static gboolean
1629 {
1630  gchar *dirname = NULL;
1631 
1633  if (self->device.name != NULL) {
1634  self->device.id =
1635  gst_tensor_src_iio_get_id_by_name (self->base_dir, self->device.name,
1636  DEVICE_PREFIX);
1637  } else if (self->device.id >= 0) {
1638  self->device.name = gst_tensor_src_iio_get_name_by_id (self->base_dir,
1639  self->device.id, DEVICE_PREFIX);
1640  } else {
1641  GST_ERROR_OBJECT (self, "IIO device information not provided.");
1642  goto error_return;
1643  }
1644  if (G_UNLIKELY (self->device.name == NULL || self->device.id < 0)) {
1645  GST_ERROR_OBJECT (self, "Cannot find the specified IIO device.");
1646  goto error_return;
1647  }
1648  dirname = g_strdup_printf ("%s%d", DEVICE_PREFIX, self->device.id);
1649  self->device.base_dir = g_build_filename (self->base_dir, dirname, NULL);
1650  g_free (dirname);
1651 
1652  return TRUE;
1653 
1654 error_return:
1655  return FALSE;
1656 }
1657 
1663 static gboolean
1665 {
1666  gchar *dirname = NULL;
1667  gchar *trigger_device_dir = NULL;
1668  gchar *filename = NULL;
1669 
1671  if (self->trigger.name != NULL || self->trigger.id >= 0) {
1673  trigger_device_dir =
1674  g_build_filename (self->device.base_dir, TRIGGER, NULL);
1675  if (!g_file_test (trigger_device_dir, G_FILE_TEST_IS_DIR)) {
1676  GST_ERROR_OBJECT (self, "IIO device %s does not supports trigger.\n",
1677  self->device.name);
1678  g_free (trigger_device_dir);
1679  goto error_return;
1680  }
1681  g_free (trigger_device_dir);
1682 
1684  if (self->trigger.name != NULL) {
1685  self->trigger.id =
1686  gst_tensor_src_iio_get_id_by_name (self->base_dir, self->trigger.name,
1687  TRIGGER_PREFIX);
1688  } else {
1689  self->trigger.name =
1690  gst_tensor_src_iio_get_name_by_id (self->base_dir, self->trigger.id,
1691  TRIGGER_PREFIX);
1692  }
1693  if (G_UNLIKELY (self->trigger.name == NULL || self->trigger.id < 0)) {
1694  GST_ERROR_OBJECT (self, "Cannot find the specified IIO trigger.");
1695  goto error_return;
1696  }
1697  dirname = g_strdup_printf ("%s%d", TRIGGER_PREFIX, self->trigger.id);
1698  self->trigger.base_dir = g_build_filename (self->base_dir, dirname, NULL);
1699  g_free (dirname);
1700 
1702  filename =
1703  g_build_filename (self->device.base_dir, TRIGGER, CURRENT_TRIGGER,
1704  NULL);
1705  if (!g_file_get_contents (filename, &self->default_trigger, NULL, NULL)) {
1706  GST_WARNING_OBJECT (self, "Unable to read default set trigger.");
1707  }
1708  g_free (filename);
1710  filename = g_build_filename (TRIGGER, CURRENT_TRIGGER, NULL);
1711  if (G_UNLIKELY (!gst_tensor_write_sysfs_string (self, filename,
1712  self->device.base_dir, self->trigger.name))) {
1713  GST_ERROR_OBJECT (self,
1714  "Cannot set the IIO device trigger: %s for device: %s.\n",
1715  self->trigger.name, self->device.name);
1716  g_free (filename);
1717  goto error_trigger_free;
1718  }
1719  g_free (filename);
1720  }
1721 
1722  return TRUE;
1723 
1724 error_trigger_free:
1725  g_free (self->trigger.base_dir);
1726  g_free (self->default_trigger);
1727  self->trigger.base_dir = NULL;
1728  self->default_trigger = NULL;
1729 
1730 error_return:
1731  return FALSE;
1732 }
1733 
1739 static gboolean
1741 {
1742  gchar *filename = NULL;
1743  gchar *file_contents = NULL;
1744  gchar *sampling_frequency_char = NULL;
1745  gint64 sampling_frequency;
1746  gboolean sampling_frequency_file_exist = TRUE;
1747 
1749  filename = g_build_filename (self->device.base_dir, SAMPLING_FREQUENCY, NULL);
1750  sampling_frequency_file_exist =
1751  g_file_test (filename, G_FILE_TEST_IS_REGULAR);
1752  if (!sampling_frequency_file_exist) {
1753  GST_WARNING_OBJECT (self, "Cannot set sampling frequency, resetting it.");
1755  self->sampling_frequency = 0;
1756  } else {
1758  if (!g_file_get_contents (filename, &file_contents, NULL, NULL)) {
1759  GST_WARNING_OBJECT (self, "Unable to read default sampling frequency.");
1760  } else if (file_contents != NULL) {
1761  self->default_sampling_frequency =
1762  g_ascii_strtoull (file_contents, NULL, 10);
1763  }
1764  g_free (file_contents);
1765  }
1766  g_free (filename);
1767 
1772  sampling_frequency =
1773  gst_tensor_src_iio_get_available_frequency (self->device.base_dir,
1774  self->sampling_frequency);
1775 
1776  if (-1 == sampling_frequency) {
1777  GST_ERROR_OBJECT (self, "Error in verifying frequency for device %s.",
1778  self->device.name);
1779  goto error_return;
1780  } else if (sampling_frequency == 0 && self->default_sampling_frequency == 0) {
1781  GST_ERROR_OBJECT (self, "Sampling frequency unknown. Unknown stream rate.");
1782  goto error_return;
1783  } else {
1784  if (0 == sampling_frequency) {
1786  GST_WARNING_OBJECT (self,
1787  "Cannot verify against sampling frequency list.");
1788  self->sampling_frequency = self->default_sampling_frequency;
1789  } else {
1790  self->sampling_frequency = sampling_frequency;
1796  if (sampling_frequency_file_exist) {
1798  sampling_frequency_char =
1799  g_strdup_printf ("%lu", (gulong) self->sampling_frequency);
1800  if (G_UNLIKELY (!gst_tensor_write_sysfs_string (self,
1801  SAMPLING_FREQUENCY, self->device.base_dir,
1802  sampling_frequency_char))) {
1803  GST_ERROR_OBJECT (self,
1804  "Cannot set the sampling frequency for device: %s.\n",
1805  self->device.name);
1806  g_free (sampling_frequency_char);
1807  goto error_return;
1808  }
1809  g_free (sampling_frequency_char);
1810  }
1811  }
1812  }
1813 
1814  g_assert (self->sampling_frequency > 0);
1815  return TRUE;
1816 
1817 error_return:
1818  return FALSE;
1819 }
1820 
1826 static gboolean
1828 {
1829  gchar *dirname = NULL, *filename = NULL;
1830  gint num_channels_enabled;
1831  GList *ch_list;
1832  gboolean item_in_table = FALSE;
1833  gint channel_en;
1834  GstTensorSrcIIOChannelProperties *channel_prop;
1835 
1836 
1838  dirname = g_build_filename (self->device.base_dir, CHANNELS, NULL);
1839  num_channels_enabled =
1841  g_free (dirname);
1842  if (G_UNLIKELY (num_channels_enabled == -1)) {
1843  GST_ERROR_OBJECT (self, "Error while scanning channels for device: %s.\n",
1844  self->device.name);
1845  goto error_return;
1846  }
1847 
1848  if ((num_channels_enabled != (gint) g_list_length (self->channels)) &&
1849  (num_channels_enabled == 0
1850  || self->channels_enabled == CHANNELS_ENABLED_ALL)) {
1851  if (!gst_tensor_set_all_channels (self, 1)) {
1853  GST_ERROR_OBJECT (self, "Enabling all channels failed for device: %s,"
1854  "disabling all the channels.\n", self->device.name);
1855  gst_tensor_set_all_channels (self, 0);
1856  goto error_channels_free;
1857  }
1858  }
1859 
1861  if (self->channels_enabled == CHANNELS_ENABLED_CUSTOM) {
1862  for (ch_list = self->channels; ch_list != NULL; ch_list = ch_list->next) {
1863  channel_prop = (GstTensorSrcIIOChannelProperties *) ch_list->data;
1864  item_in_table = g_hash_table_contains (self->custom_channel_table,
1865  GINT_TO_POINTER (channel_prop->index));
1866  channel_en = -1;
1867  if (!item_in_table && channel_prop->enabled) {
1868  channel_en = 0;
1869  channel_prop->enabled = FALSE;
1870  } else if (item_in_table && !channel_prop->enabled) {
1871  channel_en = 1;
1872  channel_prop->enabled = TRUE;
1873  }
1874  if (channel_en >= 0) {
1875  filename = g_strdup_printf ("%s%s", channel_prop->name, EN_SUFFIX);
1876  if (!gst_tensor_write_sysfs_int (self, filename, channel_prop->base_dir,
1877  channel_en)) {
1878  GST_ERROR_OBJECT (self, "Error enabling/disabling channel.");
1879  g_free (filename);
1880  goto error_channels_free;
1881  }
1882  g_free (filename);
1883  }
1884  }
1885  }
1886 
1888  g_list_foreach (self->channels, gst_tensor_channel_list_filter_enabled,
1889  &self->channels);
1890  self->scan_size = gst_tensor_get_size_from_channels (self->channels);
1891  self->num_channels_enabled = g_list_length (self->channels);
1892 
1894  gst_pad_use_fixed_caps (GST_BASE_SRC (self)->srcpad);
1895 
1897  if (!gst_tensor_src_iio_create_config (self)) {
1898  GST_ERROR_OBJECT (self, "Error creating config.\n");
1899  goto error_channels_free;
1900  }
1901 
1902  return TRUE;
1903 
1904 error_channels_free:
1905  g_list_free_full (self->channels, gst_tensor_src_iio_channel_properties_free);
1906  self->channels = NULL;
1907 
1908 error_return:
1909  return FALSE;
1910 }
1911 
1917 static gboolean
1919 {
1920  gchar *dirname = NULL;
1921  gchar *filename = NULL;
1922  gchar *file_contents = NULL;
1923  gsize length = 0;
1924  gchar *device_name = NULL;
1925 
1927  dirname = g_build_filename (self->device.base_dir, BUFFER, NULL);
1928  filename = g_build_filename (dirname, "length", NULL);
1929  if (!g_file_get_contents (filename, &file_contents, &length, NULL)) {
1930  GST_WARNING_OBJECT (self, "Unable to read default buffer capacity.");
1931  } else if (file_contents != NULL && length > 0) {
1932  self->default_buffer_capacity =
1933  (guint) g_ascii_strtoull (file_contents, NULL, 10);
1934  }
1935  g_free (file_contents);
1936  g_free (filename);
1937 
1938  if (G_UNLIKELY (!gst_tensor_write_sysfs_int (self, "length", dirname,
1939  self->buffer_capacity))) {
1940  GST_ERROR_OBJECT (self,
1941  "Cannot set the IIO device buffer capacity for device: %s.\n",
1942  self->device.name);
1943  g_free (dirname);
1944  goto error_return;
1945  }
1946  g_free (dirname);
1947 
1949  device_name = g_strdup_printf ("%s%d", DEVICE_PREFIX, self->device.id);
1950  filename = g_build_filename (self->dev_dir, device_name, NULL);
1951  g_free (device_name);
1952 
1953  self->buffer_data_fp = g_new (struct pollfd, 1);
1954  if (self->buffer_data_fp == NULL) {
1955  GST_ERROR_OBJECT (self, "Failed to allocate the file descriptor.");
1956  g_free (filename);
1957  goto error_return;
1958  }
1959 
1960  self->buffer_data_fp->events = POLLIN;
1961  self->buffer_data_fp->fd = open (filename, O_RDONLY | O_NONBLOCK);
1962  if (self->buffer_data_fp->fd < 0) {
1963  GST_ERROR_OBJECT (self, "Failed to open buffer %s for device %s.\n",
1964  filename, self->device.name);
1965  g_free (filename);
1966  g_free (self->buffer_data_fp);
1967  goto error_return;
1968  }
1969  g_free (filename);
1970 
1971  return TRUE;
1972 
1973 error_return:
1974  return FALSE;
1975 }
1976 
1981 static gboolean
1982 gst_tensor_src_iio_start (GstBaseSrc * src)
1983 {
1985  GstTensorSrcIIO *self;
1986  self = GST_TENSOR_SRC_IIO_CAST (src);
1987 
1989  if (g_ascii_strncasecmp (self->mode, MODE_ONE_SHOT,
1990  strlen (MODE_ONE_SHOT)) == 0) {
1991  GST_ERROR_OBJECT (self, "One-shot mode not yet supported.");
1992  goto error_return;
1993  }
1994 
1996  GST_ERROR_OBJECT (self, "Error setting up IIO device.");
1997  goto error_return;
1998  }
1999 
2001  GST_ERROR_OBJECT (self, "Error setting up IIO trigger for device.");
2002  goto error_device_free;
2003  }
2004 
2006  GST_ERROR_OBJECT (self, "Error setting up sampling frequency for device.");
2007  goto error_trigger_free;
2008  }
2009 
2011  GST_ERROR_OBJECT (self, "Error setting up scan channels for device.");
2012  goto error_trigger_free;
2013  }
2014 
2016  GST_ERROR_OBJECT (self, "Error setting up data buffer for device.");
2017  goto error_config_free;
2018  }
2019 
2020  self->configured = TRUE;
2022  gst_base_src_set_dynamic_size (src, FALSE);
2024  gst_base_src_start_complete (src, GST_FLOW_OK);
2025  return TRUE;
2026 
2027 error_config_free:
2028  gst_tensors_config_free (self->tensors_config);
2029  g_free (self->tensors_config);
2030 
2031  g_list_free_full (self->channels, gst_tensor_src_iio_channel_properties_free);
2032  self->channels = NULL;
2033 
2034 error_trigger_free:
2035  g_free (self->trigger.base_dir);
2036  g_free (self->default_trigger);
2037  self->trigger.base_dir = NULL;
2038  self->default_trigger = NULL;
2039 
2040 error_device_free:
2041  g_free (self->device.base_dir);
2042  self->device.base_dir = NULL;
2043 
2044 error_return:
2046  gst_base_src_start_complete (src, GST_FLOW_ERROR);
2047  return FALSE;
2048 }
2053 static void
2055 {
2056  GList *ch_list;
2057  gchar *filename = NULL, *dirname = NULL, *file_contents = NULL;
2058  GstTensorSrcIIOChannelProperties *channel_prop = NULL;
2059 
2061  for (ch_list = self->channels; ch_list != NULL; ch_list = ch_list->next) {
2062  channel_prop = (GstTensorSrcIIOChannelProperties *) ch_list->data;
2063  filename = g_strdup_printf ("%s%s", channel_prop->name, EN_SUFFIX);
2064  gst_tensor_write_sysfs_int (self, filename, channel_prop->base_dir,
2065  (int) channel_prop->pre_enabled);
2066  g_free (filename);
2067  }
2068 
2070  if (self->default_sampling_frequency > 0) {
2072  file_contents =
2073  g_strdup_printf ("%lu", (gulong) self->default_sampling_frequency);
2074  gst_tensor_write_sysfs_string (self, "sampling_frequency",
2075  self->device.base_dir, file_contents);
2076  g_free (file_contents);
2077  }
2078 
2080  dirname = g_build_filename (self->device.base_dir, BUFFER, NULL);
2081  if (self->default_buffer_capacity > 0) {
2082  gst_tensor_write_sysfs_int (self, "length", dirname,
2083  self->default_buffer_capacity);
2084  } else {
2085  gst_tensor_write_sysfs_string (self, "length", dirname, "");
2086  }
2087  g_free (dirname);
2088 
2090  if (self->default_trigger != NULL) {
2091  filename = g_build_filename (TRIGGER, CURRENT_TRIGGER, NULL);
2092  gst_tensor_write_sysfs_string (self, filename, self->device.base_dir,
2093  self->default_trigger);
2094  g_free (filename);
2095  }
2096 }
2101 static gboolean
2102 gst_tensor_src_iio_stop (GstBaseSrc * src)
2103 {
2105  GstTensorSrcIIO *self;
2106  self = GST_TENSOR_SRC_IIO_CAST (src);
2107 
2108  self->configured = FALSE;
2109 
2112 
2113  close (self->buffer_data_fp->fd);
2114  g_free (self->buffer_data_fp);
2115 
2116  gst_tensors_config_free (self->tensors_config);
2117  g_free (self->tensors_config);
2118 
2119  g_list_free_full (self->channels, gst_tensor_src_iio_channel_properties_free);
2120  self->channels = NULL;
2121 
2122  g_free (self->trigger.base_dir);
2123  g_free (self->default_trigger);
2124  self->trigger.base_dir = NULL;
2125  self->default_trigger = NULL;
2126 
2127  g_free (self->device.base_dir);
2128  self->device.base_dir = NULL;
2129 
2130  return TRUE;
2131 }
2136 static gboolean
2137 gst_tensor_src_iio_event (GstBaseSrc * src, GstEvent * event)
2138 {
2140  return GST_BASE_SRC_CLASS (parent_class)->event (src, event);
2141 }
2146 static gboolean
2147 gst_tensor_src_iio_set_caps (GstBaseSrc * src, GstCaps * caps)
2148 {
2149  GstPad *pad;
2150 
2151  pad = src->srcpad;
2152  if (!gst_pad_set_caps (pad, caps)) {
2153  return FALSE;
2154  }
2155 
2156  return TRUE;
2157 }
2158 
2164 static GstCaps *
2165 gst_tensor_src_iio_get_caps (GstBaseSrc * src, GstCaps * filter)
2166 {
2167  GstCaps *caps;
2168  GstPad *pad;
2169 
2170  pad = src->srcpad;
2171  caps = gst_pad_get_current_caps (pad);
2172  if (caps == NULL) {
2173  caps = gst_pad_get_pad_template_caps (pad);
2174  }
2175 
2176  if (filter) {
2177  GstCaps *intersection;
2178  intersection =
2179  gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
2180  gst_caps_unref (caps);
2181  caps = intersection;
2182  }
2183 
2184  return caps;
2185 }
2190 static GstCaps *
2191 gst_tensor_src_iio_fixate (GstBaseSrc * src, GstCaps * caps)
2192 {
2196  GstTensorSrcIIO *self;
2197  GstCaps *updated_caps, *fixated_caps;
2198 
2199  self = GST_TENSOR_SRC_IIO_CAST (src);
2200 
2201  if (self->is_tensor) {
2202  fixated_caps = gst_tensor_caps_from_config (self->tensors_config);
2203  } else {
2204  fixated_caps = gst_tensors_caps_from_config (self->tensors_config);
2205  }
2206 
2207  if (fixated_caps == NULL) {
2208  GST_ERROR_OBJECT (self, "Error creating fixated caps from config.");
2209  return NULL;
2210  }
2211  silent_debug (self, "Fixated caps from device = %" GST_PTR_FORMAT,
2212  fixated_caps);
2213 
2214  if (gst_caps_can_intersect (caps, fixated_caps)) {
2215  updated_caps = gst_caps_intersect (caps, fixated_caps);
2216  } else {
2217  GST_ERROR_OBJECT (self,
2218  "No intersection while fixating caps of the element.");
2219  gst_caps_unref (caps);
2220  gst_caps_unref (fixated_caps);
2221  return NULL;
2222  }
2223 
2224  gst_caps_unref (caps);
2225  gst_caps_unref (fixated_caps);
2226  return gst_caps_fixate (updated_caps);
2227 }
2232 static GstStateChangeReturn
2233 gst_tensor_src_iio_change_state (GstElement * element,
2234  GstStateChange transition)
2235 {
2236  GstTensorSrcIIO *self;
2237  GstStateChangeReturn ret;
2238  gboolean buffer_state_change_success = TRUE;
2239  gchar *dirname = NULL;
2240 
2241  self = GST_TENSOR_SRC_IIO (element);
2242 
2243  switch (transition) {
2244  case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2245  {
2247  dirname = g_build_filename (self->device.base_dir, BUFFER, NULL);
2248  if (G_UNLIKELY (!gst_tensor_write_sysfs_int (self, "enable", dirname, 1))) {
2249  GST_ERROR_OBJECT (self,
2250  "Cannot enable the IIO device buffer for device: %s.\n",
2251  self->device.name);
2252  buffer_state_change_success = FALSE;
2253  }
2254  g_free (dirname);
2255  break;
2256  }
2257  default:
2258  break;
2259  }
2260 
2261  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2262 
2263  switch (transition) {
2264  case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2265  {
2267  dirname = g_build_filename (self->device.base_dir, BUFFER, NULL);
2268  if (G_UNLIKELY (!gst_tensor_write_sysfs_int (self, "enable", dirname, 0))) {
2269  GST_ERROR_OBJECT (self,
2270  "Error in disabling the IIO device buffer for device: %s.\n",
2271  self->device.name);
2272  buffer_state_change_success = FALSE;
2273  }
2274  g_free (dirname);
2275  break;
2276  }
2277  default:
2278  break;
2279  }
2280 
2281  if (!buffer_state_change_success) {
2282  ret = GST_STATE_CHANGE_FAILURE;
2283  }
2284 
2285  return ret;
2286 }
2291 static gboolean
2292 gst_tensor_src_iio_is_seekable (GstBaseSrc * src)
2293 {
2294  UNUSED (src);
2296  return FALSE;
2297 }
2302 static void
2303 gst_tensor_src_iio_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
2304  GstClockTime * start, GstClockTime * end)
2305 {
2306  GstClockTime timestamp;
2307  GstClockTime duration;
2308  UNUSED (basesrc);
2309 
2310  timestamp = GST_BUFFER_DTS (buffer);
2311  duration = GST_BUFFER_DURATION (buffer);
2312 
2314  if (!GST_CLOCK_TIME_IS_VALID (timestamp))
2315  timestamp = GST_BUFFER_PTS (buffer);
2316 
2317  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
2318  *start = timestamp;
2319  if (GST_CLOCK_TIME_IS_VALID (duration)) {
2320  *end = timestamp + duration;
2321  }
2322  }
2323 }
2324 
2329 static GstFlowReturn
2330 gst_tensor_src_iio_create (GstBaseSrc * src, guint64 offset,
2331  guint size, GstBuffer ** buffer)
2332 {
2333  GstTensorSrcIIO *self;
2334  GstFlowReturn ret = GST_FLOW_ERROR;
2335  GstBuffer *buf;
2336  GstMemory *mem;
2337  GstTensorInfo *_info;
2338  gsize buffer_size;
2339  guint idx = 0;
2340  UNUSED (size);
2341 
2342  self = GST_TENSOR_SRC_IIO_CAST (src);
2343  buf = gst_buffer_new ();
2344  buffer_size = gst_tensors_info_get_size (&self->tensors_config->info, 0);
2345 
2346  for (idx = 0; idx < self->tensors_config->info.num_tensors; idx++) {
2348  _info = gst_tensors_info_get_nth_info (&self->tensors_config->info, idx);
2349  g_assert (buffer_size == gst_tensor_info_get_size (_info));
2350 
2351  mem = gst_allocator_alloc (NULL, buffer_size, NULL);
2352  if (mem == NULL) {
2353  GST_ERROR_OBJECT (self, "Error allocating memory for buffer.");
2354  goto error;
2355  }
2356 
2357  gst_tensor_buffer_append_memory (buf, mem, _info);
2358  }
2359 
2360  ret = gst_tensor_src_iio_fill (src, offset, (guint) buffer_size, buf);
2361 
2362 error:
2363  if (ret == GST_FLOW_OK)
2364  *buffer = buf;
2365  else
2366  gst_buffer_unref (buf);
2367 
2368  return ret;
2369 }
2370 
2380 static gboolean
2382  prop, gchar * data, gfloat * buffer_map)
2383 {
2384  guint64 storage_mask;
2385  switch (prop->storage_bytes) {
2386  case 1:
2387  {
2388  guint8 value = *(guint8 *) (data + prop->location);
2390  value >>= (8 - prop->storage_bits);
2391  *buffer_map =
2392  gst_tensor_src_iio_process_scanned_data_from_guint8 (prop, value);
2393  break;
2394  }
2395  case 2:
2396  {
2397  guint16 value = *(guint16 *) (data + prop->location);
2398  if (prop->big_endian) {
2399  value = GUINT16_FROM_BE (value);
2401  value >>= (16 - prop->storage_bits);
2402  } else {
2403  value = GUINT16_FROM_LE (value);
2405  storage_mask = G_MAXUINT64 >> (64 - prop->storage_bits);
2406  value &= storage_mask;
2407  }
2408  *buffer_map =
2409  gst_tensor_src_iio_process_scanned_data_from_guint16 (prop, value);
2410  break;
2411  }
2412  case 3:
2414  case 4:
2415  {
2416  guint32 value = *(guint32 *) (data + prop->location);
2417  if (prop->big_endian) {
2418  value = GUINT32_FROM_BE (value);
2420  value >>= (32 - prop->storage_bits);
2421  } else {
2422  value = GUINT32_FROM_LE (value);
2424  storage_mask = G_MAXUINT64 >> (64 - prop->storage_bits);
2425  value &= storage_mask;
2426  }
2427  *buffer_map =
2428  gst_tensor_src_iio_process_scanned_data_from_guint32 (prop, value);
2429  break;
2430  }
2431  case 5:
2433  case 6:
2435  case 7:
2437  case 8:
2438  {
2439  guint64 value = *(guint64 *) (data + prop->location);
2440  if (prop->big_endian) {
2441  value = GUINT64_FROM_BE (value);
2443  value >>= (64 - prop->storage_bits);
2444  } else {
2445  value = GUINT64_FROM_LE (value);
2447  storage_mask = G_MAXUINT64 >> (64 - prop->storage_bits);
2448  value &= storage_mask;
2449  }
2450  *buffer_map =
2451  gst_tensor_src_iio_process_scanned_data_from_guint64 (prop, value);
2452  break;
2453  }
2454  default:
2455  GST_ERROR ("Storage bytes for channel %s out of bounds", prop->name);
2456  return FALSE;
2457  }
2458  return TRUE;
2459 }
2460 
2466 static GstFlowReturn
2467 gst_tensor_src_iio_fill (GstBaseSrc * src, guint64 offset, guint size,
2468  GstBuffer * buffer)
2469 {
2470  GstTensorSrcIIO *self;
2471  GstFlowReturn ret = GST_FLOW_ERROR;
2472  gint status, bytes_to_read;
2473  guint idx, ch_idx, num_mapped;
2474  gchar *raw_data_base, *raw_data;
2475  gfloat *map_data_float;
2476  GstMemory *mem[NNS_TENSOR_SIZE_LIMIT];
2477  GstMapInfo map[NNS_TENSOR_SIZE_LIMIT];
2478  guint64 time_to_end, cur_time;
2479  guint64 safe_multiply;
2480  GList *channels;
2481  UNUSED (offset);
2482  UNUSED (size);
2483 
2484  self = GST_TENSOR_SRC_IIO (src);
2485 
2488  self->tensors_config->info.num_tensors);
2489 
2491  num_mapped = 0;
2492  for (idx = 0; idx < self->tensors_config->info.num_tensors; idx++) {
2493  mem[idx] = gst_tensor_buffer_get_nth_memory (buffer, idx);
2494  if (!gst_memory_map (mem[idx], &map[idx], GST_MAP_WRITE)) {
2495  for (ch_idx = 0; ch_idx < num_mapped; ch_idx++) {
2496  gst_memory_unmap (mem[ch_idx], &map[ch_idx]);
2497  gst_memory_unref (mem[ch_idx]);
2498  }
2499  gst_memory_unref (mem[idx]);
2500  return GST_FLOW_ERROR;
2501  }
2502  num_mapped = idx + 1;
2503  }
2505  bytes_to_read = self->scan_size * self->buffer_capacity;
2506  raw_data_base = g_malloc (bytes_to_read);
2507  if (raw_data_base == NULL) {
2508  GST_ERROR_OBJECT (self, "Failed to allocate memory to read raw data.");
2509  goto error_data_free;
2510  }
2511 
2513  time_to_end = g_get_real_time () + self->poll_timeout * 1000;
2514  while (TRUE) {
2515  if (self->trigger.name != NULL) {
2516  status = poll (self->buffer_data_fp, 1, self->poll_timeout);
2517  if (status < 0) {
2518  GST_ERROR_OBJECT (self, "Error %d while polling the buffer.", status);
2519  goto error_data_free;
2520  } else if (status == 0) {
2521  GST_ERROR_OBJECT (self, "Timeout while polling the buffer.");
2522  goto error_data_free;
2523  } else if (!(self->buffer_data_fp->revents & POLLIN)) {
2524  GST_ERROR_OBJECT (self, "Poll succeeded on an unexpected event %d.",
2525  self->buffer_data_fp->revents);
2526  goto error_data_free;
2527  }
2528  self->buffer_data_fp->revents = 0;
2529  } else {
2531  if (g_uint64_checked_mul (&safe_multiply, G_USEC_PER_SEC,
2532  self->buffer_capacity)) {
2533  g_usleep (MAX (1, safe_multiply / self->sampling_frequency));
2534  } else {
2535  g_usleep (MAX (1,
2536  (self->buffer_capacity / self->sampling_frequency) *
2537  G_USEC_PER_SEC));
2538  }
2539  }
2540 
2542  status = read (self->buffer_data_fp->fd, raw_data_base, bytes_to_read);
2543  if (status < bytes_to_read) {
2544  if (errno == EAGAIN) {
2545  GST_WARNING_OBJECT (self, "EAGAIN error, try again.");
2546  cur_time = g_get_real_time ();
2547  if (time_to_end >= cur_time) {
2548  continue;
2549  } else {
2550  GST_ERROR_OBJECT (self, "EAGAIN timeout expired.");
2551  goto error_data_free;
2552  }
2553  }
2554  GST_ERROR_OBJECT (self,
2555  "Error no %d: read %d/%d bytes while reading from the buffer fd.",
2556  errno, status, bytes_to_read);
2557  goto error_data_free;
2558  }
2559  break;
2560  }
2561 
2563  raw_data = raw_data_base;
2564 
2569  for (idx = 0; idx < self->buffer_capacity; idx++) {
2570  for (channels = self->channels, ch_idx = 0;
2571  ch_idx < self->num_channels_enabled;
2572  ch_idx++, channels = channels->next) {
2573  if (self->tensors_config->info.num_tensors == 1) {
2575  map_data_float =
2576  ((gfloat *) map[0].data) + idx * self->num_channels_enabled +
2577  ch_idx;
2578  } else {
2580  map_data_float = ((gfloat *) map[ch_idx].data) + idx;
2581  }
2582  if (!gst_tensor_src_iio_process_scanned_data (channels->data, raw_data,
2583  map_data_float)) {
2584  GST_ERROR_OBJECT (self, "Error while processing scanned data.");
2585  goto error_data_free;
2586  }
2587  }
2588  raw_data += self->scan_size;
2589  }
2590 
2591  ret = GST_FLOW_OK;
2592 
2593 error_data_free:
2594  g_free (raw_data_base);
2595  for (idx = 0; idx < self->tensors_config->info.num_tensors; idx++) {
2596  gst_memory_unmap (mem[idx], &map[idx]);
2597  gst_memory_unref (mem[idx]);
2598  }
2599 
2600  return ret;
2601 }
gst_tensor_src_iio_is_seekable
static gboolean gst_tensor_src_iio_is_seekable(GstBaseSrc *src)
check if source supports seeking
Definition: gsttensor_srciio.c:2287
DEFAULT_OPERATING_MODE
#define DEFAULT_OPERATING_MODE
Definition: gsttensor_srciio.c:168
GST_TENSOR_CAP_DEFAULT
#define GST_TENSOR_CAP_DEFAULT
Default static capability for other/tensor.
Definition: tensor_typedef.h:78
PROP_TRIGGER
@ PROP_TRIGGER
Definition: gsttensor_srciio.c:141
g_assert
g_assert(sizeof(DTYPE_UNSIGNED)==sizeof(DTYPE_SIGNED))
_GstTensorSrcIIO::num_channels_enabled
guint num_channels_enabled
Definition: gsttensor_srciio.h:123
gst_tensor_src_iio_get_property
static void gst_tensor_src_iio_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
get tensor_src_iio properties
Definition: gsttensor_srciio.c:1264
gst_tensor_src_iio_set_caps
static gboolean gst_tensor_src_iio_set_caps(GstBaseSrc *src, GstCaps *caps)
set new caps
Definition: gsttensor_srciio.c:2142
GstTensorInfo::name
char * name
Definition: tensor_typedef.h:263
data
svtc_1 data
Definition: gsttensor_if.c:844
GstTensorInfo
Internal data structure for tensor info.
Definition: tensor_typedef.h:261
ml_logw
#define ml_logw
Definition: nnstreamer_log.h:77
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
CHANNELS_ENABLED_CUSTOM
@ CHANNELS_ENABLED_CUSTOM
Definition: gsttensor_srciio.h:58
_GstTensorSrcIIOClass
GstTensorSrcIIOClass data structure.
Definition: gsttensor_srciio.h:143
gst_tensor_src_iio_start
static gboolean gst_tensor_src_iio_start(GstBaseSrc *src)
start function, called when state changed null to ready. load the device and init the device resource...
Definition: gsttensor_srciio.c:1977
FALSE
return FALSE
Definition: gsttensor_transform.c:590
DEVICE_PREFIX
#define DEVICE_PREFIX
Definition: gsttensor_srciio.c:227
_GstTensorSrcIIOChannelProperties::storage_bits
guint storage_bits
Definition: gsttensor_srciio.h:92
_GstTensorSrcIIOChannelProperties::scale
gfloat scale
Definition: gsttensor_srciio.h:96
prop
GstTensorSrcIIOChannelProperties * prop
DTYPE_UNSIGNED ( .
Definition: gsttensor_srciio.c:110
DBG
#define DBG
Macro for debug mode.
Definition: gsttensor_srciio.c:97
MIN_BUFFER_CAPACITY
#define MIN_BUFFER_CAPACITY
Minimum and maximum buffer length for iio.
Definition: gsttensor_srciio.c:183
gst_tensor_src_iio_setup_device_buffer
static gboolean gst_tensor_src_iio_setup_device_buffer(GstTensorSrcIIO *self)
setup device using name/id
Definition: gsttensor_srciio.c:1913
DEFAULT_PROP_DEV_DIRECTORY
#define DEFAULT_PROP_DEV_DIRECTORY
Definition: gsttensor_srciio.c:154
gst_tensor_src_iio_setup_device_properties
static gboolean gst_tensor_src_iio_setup_device_properties(GstTensorSrcIIO *self)
setup device using name/id
Definition: gsttensor_srciio.c:1623
gst_tensor_src_iio_event
static gboolean gst_tensor_src_iio_event(GstBaseSrc *src, GstEvent *event)
handle events
Definition: gsttensor_srciio.c:2132
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
_GstTensorSrcIIO::is_tensor
gboolean is_tensor
Definition: gsttensor_srciio.h:125
_GstTensorSrcIIO::merge_channels_data
gboolean merge_channels_data
Definition: gsttensor_srciio.h:124
_GstTensorSrcIIO
GstTensorSrcIIO data structure.
Definition: gsttensor_srciio.h:104
MAX_POLL_TIMEOUT
#define MAX_POLL_TIMEOUT
Definition: gsttensor_srciio.c:199
MAX_BUFFER_CAPACITY
#define MAX_BUFFER_CAPACITY
Definition: gsttensor_srciio.c:184
DEFAULT_PROP_DEVICE_NUM
#define DEFAULT_PROP_DEVICE_NUM
default trigger and device numbers
Definition: gsttensor_srciio.c:210
gst_tensor_src_iio_change_state
static GstStateChangeReturn gst_tensor_src_iio_change_state(GstElement *element, GstStateChange transition)
Perform state change.
Definition: gsttensor_srciio.c:2228
gst_tensor_src_iio_fill
static GstFlowReturn gst_tensor_src_iio_fill(GstBaseSrc *src, guint64 offset, guint size, GstBuffer *buf)
fill the buffer with data
Definition: gsttensor_srciio.c:2462
_GstTensorSrcIIOChannelProperties::big_endian
gboolean big_endian
Definition: gsttensor_srciio.h:87
GstTensorsConfig::rate_d
int rate_d
Definition: tensor_typedef.h:288
_GstTensorSrcIIO::tensors_config
GstTensorsConfig * tensors_config
Definition: gsttensor_srciio.h:135
DEFAULT_PROP_BASE_DIRECTORY
#define DEFAULT_PROP_BASE_DIRECTORY
IIO system paths.
Definition: gsttensor_srciio.c:153
_GstTensorSrcIIOChannelProperties::mask
guint64 mask
Definition: gsttensor_srciio.h:90
gst_tensor_channel_list_filter_enabled
static void gst_tensor_channel_list_filter_enabled(gpointer data, gpointer user_data)
compare channels for filtering if enabled
Definition: gsttensor_srciio.c:836
DEFAULT_BUFFER_CAPACITY
#define DEFAULT_BUFFER_CAPACITY
Definition: gsttensor_srciio.c:185
gst_tensor_src_iio_get_available_frequency
static gint64 gst_tensor_src_iio_get_available_frequency(const gchar *base_dir, const guint64 frequency)
return sampling frequency given the frequency input from user
Definition: gsttensor_srciio.c:1036
silent_debug
#define silent_debug(self,...)
Macro for debug message.
Definition: tensor_common.h:276
TIMESTAMP
#define TIMESTAMP
Definition: gsttensor_srciio.c:226
gst_tensor_src_iio_init
static void gst_tensor_src_iio_init(GstTensorSrcIIO *self)
initialize tensor_src_iio element.
Definition: gsttensor_srciio.c:439
PROP_BASE_DIRECTORY
@ PROP_BASE_DIRECTORY
Definition: gsttensor_srciio.c:137
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_srciio.c:136
g_free
g_free(self->option[(opnum) - 1])
opnum: \
PROP_0
@ PROP_0
Definition: gsttensor_srciio.c:134
CHANNELS_ENABLED_AUTO
@ CHANNELS_ENABLED_AUTO
Definition: gsttensor_srciio.h:57
_GstTensorSrcIIOChannelProperties::index
gint index
Definition: gsttensor_srciio.h:85
TRIGGER
#define TRIGGER
Definition: gsttensor_srciio.c:223
g_value_set_string
g_value_set_string(value, self->option[opnum - 1])
opnum: \
GstTensorsConfig::rate_n
int rate_n
Definition: tensor_typedef.h:287
gst_tensor_src_iio_set_property
static void gst_tensor_src_iio_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
set tensor_src_iio properties
Definition: gsttensor_srciio.c:1098
gst_tensor_src_merge_tensor_by_type
static gint gst_tensor_src_merge_tensor_by_type(GstTensorInfo *info, guint size, guint dir)
merge multiple other/tensor
Definition: gsttensor_srciio.c:491
TRIGGER_PREFIX
#define TRIGGER_PREFIX
Definition: gsttensor_srciio.c:228
gst_tensor_src_iio_setup_trigger_properties
static gboolean gst_tensor_src_iio_setup_trigger_properties(GstTensorSrcIIO *self)
setup trigger using name/id
Definition: gsttensor_srciio.c:1659
OFFSET_SUFFIX
#define OFFSET_SUFFIX
Definition: gsttensor_srciio.c:238
CHANNELS_ENABLED_ALL
@ CHANNELS_ENABLED_ALL
Definition: gsttensor_srciio.h:56
gst_tensor_src_restore_iio_device
static void gst_tensor_src_restore_iio_device(GstTensorSrcIIO *self)
restore the iio device to its original device.
Definition: gsttensor_srciio.c:2049
gst_tensor_src_iio_class_init
static void gst_tensor_src_iio_class_init(GstTensorSrcIIOClass *klass)
initialize the tensor_src_iio class.
Definition: gsttensor_srciio.c:287
PROP_BUFFER_CAPACITY
@ PROP_BUFFER_CAPACITY
Definition: gsttensor_srciio.c:144
_NNS_FLOAT32
@ _NNS_FLOAT32
Definition: tensor_typedef.h:147
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
_GstTensorSrcIIOChannelProperties::used_bits
guint used_bits
Definition: gsttensor_srciio.h:89
gst_tensor_src_iio_finalize
static void gst_tensor_src_iio_finalize(GObject *object)
finalize the instance
Definition: gsttensor_srciio.c:1358
CURRENT_TRIGGER
#define CURRENT_TRIGGER
Definition: gsttensor_srciio.c:229
gst_tensor_src_iio_device_properties_init
static void gst_tensor_src_iio_device_properties_init(GstTensorSrcIIODeviceProperties *prop)
initialize GstTensorSrcIIODeviceProperties structure
Definition: gsttensor_srciio.c:427
gst_tensor_src_iio_get_caps
static GstCaps * gst_tensor_src_iio_get_caps(GstBaseSrc *src, GstCaps *filter)
get caps of subclass
Definition: gsttensor_srciio.c:2160
gst_tensor_src_iio_channel_properties_free
static void gst_tensor_src_iio_channel_properties_free(gpointer data)
delete GstTensorSrcIIODeviceProperties structure
Definition: gsttensor_srciio.c:411
_GstTensorSrcIIODeviceProperties
GstTensorSrcIIO devices's properties (internal data structure)
Definition: gsttensor_srciio.h:67
gst_tensor_caps_from_config
GstCaps * gst_tensor_caps_from_config(const GstTensorsConfig *config)
Get tensor caps from tensors config (for other/tensor)
Definition: nnstreamer_plugin_api_impl.c:1395
gsttensor_srciio.h
GStreamer plugin to support linux IIO as tensor(s)
GstTensorsConfig
Internal data structure for configured tensors info (for other/tensors).
Definition: tensor_typedef.h:284
gst_tensor_info_init
void gst_tensor_info_init(GstTensorInfo *info)
Initialize the tensor info structure.
Definition: nnstreamer_plugin_api_util_impl.c:121
GST_TENSOR_SRC_IIO
#define GST_TENSOR_SRC_IIO(obj)
Definition: gsttensor_srciio.h:39
gst_tensor_src_iio_set_channel_type
static gboolean gst_tensor_src_iio_set_channel_type(GstTensorSrcIIOChannelProperties *prop, const gchar *contents)
get type info about the channel from the string
Definition: gsttensor_srciio.c:718
gst_tensor_write_sysfs_string
static gboolean gst_tensor_write_sysfs_string(GstTensorSrcIIO *self, const gchar *file, const gchar *base_dir, const gchar *contents)
write the string in to the file
Definition: gsttensor_srciio.c:1384
TRUE
return TRUE
Definition: gsttensor_if.c:897
UNUSED
#define UNUSED(expr)
Definition: mqttcommon.h:19
PROP_DEVICE_NUM
@ PROP_DEVICE_NUM
Definition: gsttensor_srciio.c:140
DEFAULT_MERGE_CHANNELS
#define DEFAULT_MERGE_CHANNELS
Default behavior on merging channels.
Definition: gsttensor_srciio.c:205
nnstreamer_util.h
Optional NNStreamer utility functions for sub-plugin writers and users.
gst_tensor_channel_list_sort_cmp
static gint gst_tensor_channel_list_sort_cmp(gconstpointer a, gconstpointer b)
compare channels for sort based on their indices
Definition: gsttensor_srciio.c:822
gst_tensor_src_iio_get_generic_name
static gchar * gst_tensor_src_iio_get_generic_name(const gchar *channel_name)
get generic name for channel from the string
Definition: gsttensor_srciio.c:799
NAME_FILE
#define NAME_FILE
filenames for IIO devices/triggers characteristics
Definition: gsttensor_srciio.c:243
PROP_FREQUENCY
@ PROP_FREQUENCY
Definition: gsttensor_srciio.c:145
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
_GstTensorSrcIIOChannelProperties::name
gchar * name
Definition: gsttensor_srciio.h:81
gst_tensor_info_is_equal
gboolean gst_tensor_info_is_equal(const GstTensorInfo *i1, const GstTensorInfo *i2)
Compare tensor info.
Definition: nnstreamer_plugin_api_util_impl.c:197
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorSrcIIO, gst_tensor_src_iio, GST_TYPE_BASE_SRC)
AVAIL_FREQUENCY_FILE
#define AVAIL_FREQUENCY_FILE
Definition: gsttensor_srciio.c:244
DEFAULT_OPERATING_CHANNELS_ENABLED
#define DEFAULT_OPERATING_CHANNELS_ENABLED
Definition: gsttensor_srciio.c:161
gst_tensor_set_all_channels
static gboolean gst_tensor_set_all_channels(GstTensorSrcIIO *self, const gint contents)
set value to all the channels
Definition: gsttensor_srciio.c:1469
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
_GstTensorSrcIIOChannelProperties::shift
guint shift
Definition: gsttensor_srciio.h:93
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
DEFAULT_PROP_STRING
#define DEFAULT_PROP_STRING
Flag for general default value of string.
Definition: gsttensor_srciio.c:178
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
gst_tensor_src_iio_get_times
static void gst_tensor_src_iio_get_times(GstBaseSrc *basesrc, GstBuffer *buffer, GstClockTime *start, GstClockTime *end)
returns the time for the buffers
Definition: gsttensor_srciio.c:2298
PROCESS_SCANNED_DATA
#define PROCESS_SCANNED_DATA(DTYPE_UNSIGNED, DTYPE_SIGNED)
Macro to generate data processing functions for various types.
Definition: gsttensor_srciio.c:106
_GstTensorSrcIIOChannelProperties::storage_bytes
guint storage_bytes
Definition: gsttensor_srciio.h:91
gst_tensor_src_iio_get_all_channel_info
static gint gst_tensor_src_iio_get_all_channel_info(GstTensorSrcIIO *self, const gchar *dir_name)
get info about all the channels in the device
Definition: gsttensor_srciio.c:860
_GstTensorSrcIIOChannelProperties::generic_name
gchar * generic_name
Definition: gsttensor_srciio.h:82
gst_tensor_src_iio_get_name_by_id
static gchar * gst_tensor_src_iio_get_name_by_id(const gchar *dir_name, const gint id, const gchar *prefix)
check if device/trigger with the given id exists
Definition: gsttensor_srciio.c:640
MAX_FREQUENCY
#define MAX_FREQUENCY
Definition: gsttensor_srciio.c:192
MIN_POLL_TIMEOUT
#define MIN_POLL_TIMEOUT
Minimum and maximum polling timeout for the buffered reading.
Definition: gsttensor_srciio.c:198
gst_tensor_src_iio_create
static GstFlowReturn gst_tensor_src_iio_create(GstBaseSrc *src, guint64 offset, guint size, GstBuffer **buf)
create a buffer with requested size and offset
Definition: gsttensor_srciio.c:2325
PROP_DEVICE
@ PROP_DEVICE
Definition: gsttensor_srciio.c:139
GstTensorsInfo::num_tensors
unsigned int num_tensors
Definition: tensor_typedef.h:275
_GstTensorSrcIIO::buffer_capacity
guint buffer_capacity
Definition: gsttensor_srciio.h:126
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
_GstTensorSrcIIOChannelProperties::base_file
gchar * base_file
Definition: gsttensor_srciio.h:84
_GstTensorSrcIIOChannelProperties::location
guint location
Definition: gsttensor_srciio.h:94
PROP_CHANNELS
@ PROP_CHANNELS
Definition: gsttensor_srciio.c:143
PROP_DEV_DIRECTORY
@ PROP_DEV_DIRECTORY
Definition: gsttensor_srciio.c:138
DEFAULT_PROP_SILENT
#define DEFAULT_PROP_SILENT
Flag to print minimized log.
Definition: gsttensor_srciio.c:173
_GstTensorSrcIIOChannelProperties::base_dir
gchar * base_dir
Definition: gsttensor_srciio.h:83
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
_GstTensorSrcIIOChannelProperties::is_signed
gboolean is_signed
Definition: gsttensor_srciio.h:88
gst_tensor_get_size_from_channels
static guint gst_tensor_get_size_from_channels(GList *channels)
get the size of the combined data from channels
Definition: gsttensor_srciio.c:1499
_GstTensorSrcIIOChannelProperties::enabled
gboolean enabled
Definition: gsttensor_srciio.h:79
gst_tensor_src_iio_fixate
static GstCaps * gst_tensor_src_iio_fixate(GstBaseSrc *src, GstCaps *caps)
fixate the caps when needed during negotiation
Definition: gsttensor_srciio.c:2186
PROP_MERGE_CHANNELS
@ PROP_MERGE_CHANNELS
Definition: gsttensor_srciio.c:146
DEFAULT_FREQUENCY
#define DEFAULT_FREQUENCY
Definition: gsttensor_srciio.c:193
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_TENSOR_SRC_IIO_CAST
#define GST_TENSOR_SRC_IIO_CAST(obj)
Definition: gsttensor_srciio.h:47
gst_tensor_write_sysfs_int
static gboolean gst_tensor_write_sysfs_int(GstTensorSrcIIO *self, const gchar *file, const gchar *base_dir, const gint contents)
write the int in to the file
Definition: gsttensor_srciio.c:1449
_GstTensorSrcIIOChannelProperties::offset
gfloat offset
Definition: gsttensor_srciio.h:95
_GstTensorSrcIIOChannelProperties
GstTensorSrcIIO channel's properties (internal data structure)
Definition: gsttensor_srciio.h:77
GstTensorInfo::type
tensor_type type
Definition: tensor_typedef.h:266
GstTensorsConfig::info
GstTensorsInfo info
Definition: tensor_typedef.h:286
SAMPLING_FREQUENCY
#define SAMPLING_FREQUENCY
Definition: gsttensor_srciio.c:245
CHANNELS_ENABLED_AUTO_CHAR
#define CHANNELS_ENABLED_AUTO_CHAR
iio device channel enabled mode
Definition: gsttensor_srciio.c:159
_GstTensorSrcIIO::channels
GList * channels
Definition: gsttensor_srciio.h:118
INDEX_SUFFIX
#define INDEX_SUFFIX
Definition: gsttensor_srciio.c:235
MIN_FREQUENCY
#define MIN_FREQUENCY
Minimum and maximum operating frequency for the device Frequency 0 chooses the first available freque...
Definition: gsttensor_srciio.c:191
EN_SUFFIX
#define EN_SUFFIX
IIO device channels.
Definition: gsttensor_srciio.c:234
PROP_POLL_TIMEOUT
@ PROP_POLL_TIMEOUT
Definition: gsttensor_srciio.c:147
gst_tensor_src_iio_get_id_by_name
static gint gst_tensor_src_iio_get_id_by_name(const gchar *dir_name, const gchar *name, const gchar *prefix)
check if device/trigger with the given name exists
Definition: gsttensor_srciio.c:576
gst_tensor_src_iio_get_float_from_file
static gboolean gst_tensor_src_iio_get_float_from_file(const gchar *dirname, const gchar *name, const gchar *suffix, gfloat *value)
parse float value from the file
Definition: gsttensor_srciio.c:677
CHANNELS
#define CHANNELS
Definition: gsttensor_srciio.c:224
GstTensorInfo::dimension
tensor_dim dimension
Definition: tensor_typedef.h:267
gst_tensor_src_iio_setup_scan_channels
static gboolean gst_tensor_src_iio_setup_scan_channels(GstTensorSrcIIO *self)
setup scan channels for the device
Definition: gsttensor_srciio.c:1822
if
value_unsigned & if(prop->is_signed)
Definition: gsttensor_srciio.c:117
gst_tensor_src_iio_process_scanned_data
static gboolean gst_tensor_src_iio_process_scanned_data(GstTensorSrcIIOChannelProperties *prop, gchar *data, gfloat *buffer_map)
process the scanned data from IIO device
Definition: gsttensor_srciio.c:2376
PROP_MODE
@ PROP_MODE
Definition: gsttensor_srciio.c:135
_GstTensorSrcIIO::sampling_frequency
guint64 sampling_frequency
Definition: gsttensor_srciio.h:127
gst_tensor_src_iio_setup_sampling_frequency
static gboolean gst_tensor_src_iio_setup_sampling_frequency(GstTensorSrcIIO *self)
setup device sampling frequency
Definition: gsttensor_srciio.c:1735
PROP_TRIGGER_NUM
@ PROP_TRIGGER_NUM
Definition: gsttensor_srciio.c:142
NNS_TENSOR_RANK_LIMIT
#define NNS_TENSOR_RANK_LIMIT
Definition: tensor_typedef.h:34
BUFFER
#define BUFFER
Definition: gsttensor_srciio.c:222
DEFAULT_PROP_TRIGGER_NUM
#define DEFAULT_PROP_TRIGGER_NUM
Definition: gsttensor_srciio.c:211
TYPE_SUFFIX
#define TYPE_SUFFIX
Definition: gsttensor_srciio.c:236
GST_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensor_src_iio_debug)
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
MODE_ONE_SHOT
#define MODE_ONE_SHOT
tensor_src_iio device modes
Definition: gsttensor_srciio.c:166
SCALE_SUFFIX
#define SCALE_SUFFIX
Definition: gsttensor_srciio.c:237
DEFAULT_POLL_TIMEOUT
#define DEFAULT_POLL_TIMEOUT
Definition: gsttensor_srciio.c:200
CHANNELS_ENABLED_ALL_CHAR
#define CHANNELS_ENABLED_ALL_CHAR
Definition: gsttensor_srciio.c:160
GST_ERROR
GST_ERROR("Failed to register nnstreamer plugin : tensor_" # name)
type)) { \
gst_tensor_src_iio_create_config
static gboolean gst_tensor_src_iio_create_config(GstTensorSrcIIO *tensor_src_iio)
create the structure for the caps to update the src pad caps
Definition: gsttensor_srciio.c:1527
_GstTensorSrcIIOChannelProperties::pre_enabled
gboolean pre_enabled
Definition: gsttensor_srciio.h:80
gst_tensor_src_iio_stop
static gboolean gst_tensor_src_iio_stop(GstBaseSrc *src)
stop function, called when state changed ready to null.
Definition: gsttensor_srciio.c:2097