Doxygen Book
gsttensor_crop.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-only */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41 
42 #include <string.h>
43 #include <nnstreamer_util.h>
44 #include "gsttensor_crop.h"
45 #include "tensor_data.h"
46 
50 typedef struct
51 {
52  guint x;
53  guint y;
54  guint w;
55  guint h;
57 
62 typedef struct
63 {
64  guint num;
67 
68 GST_DEBUG_CATEGORY_STATIC (gst_tensor_crop_debug);
69 #define GST_CAT_DEFAULT gst_tensor_crop_debug
70 
74 enum
75 {
79 };
80 
84 #define DEFAULT_SILENT TRUE
85 
89 #define DEFAULT_LATENESS (-1)
90 
94 static GstStaticPadTemplate raw_template = GST_STATIC_PAD_TEMPLATE ("raw",
95  GST_PAD_SINK,
96  GST_PAD_ALWAYS,
97  GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT ";"
98  GST_TENSORS_CAP_MAKE ("{ static, flexible }")));
99 
103 static GstStaticPadTemplate info_template = GST_STATIC_PAD_TEMPLATE ("info",
104  GST_PAD_SINK,
105  GST_PAD_ALWAYS,
106  GST_STATIC_CAPS (GST_TENSORS_FLEX_CAP_DEFAULT));
107 
111 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
112  GST_PAD_SRC,
113  GST_PAD_ALWAYS,
114  GST_STATIC_CAPS (GST_TENSORS_FLEX_CAP_DEFAULT));
115 
116 #define gst_tensor_crop_parent_class parent_class
117 G_DEFINE_TYPE (GstTensorCrop, gst_tensor_crop, GST_TYPE_ELEMENT);
118 
119 static void gst_tensor_crop_finalize (GObject * object);
120 static void gst_tensor_crop_set_property (GObject * object, guint prop_id,
121  const GValue * value, GParamSpec * pspec);
122 static void gst_tensor_crop_get_property (GObject * object, guint prop_id,
123  GValue * value, GParamSpec * pspec);
124 static GstStateChangeReturn gst_tensor_crop_change_state (GstElement * element,
125  GstStateChange transition);
126 static gboolean gst_tensor_crop_src_event (GstPad * pad, GstObject * parent,
127  GstEvent * event);
128 static gboolean gst_tensor_crop_sink_event (GstCollectPads * pads,
129  GstCollectData * data, GstEvent * event, gpointer user_data);
130 static GstFlowReturn gst_tensor_crop_collected (GstCollectPads * pads,
131  gpointer user_data);
132 
136 static void
138 {
139  GObjectClass *object_class;
140  GstElementClass *element_class;
141 
142  GST_DEBUG_CATEGORY_INIT (gst_tensor_crop_debug, "tensor_crop", 0,
143  "Element to crop the regions of incoming tensor");
144 
145  object_class = (GObjectClass *) klass;
146  element_class = (GstElementClass *) klass;
147 
148  object_class->set_property = gst_tensor_crop_set_property;
149  object_class->get_property = gst_tensor_crop_get_property;
150  object_class->finalize = gst_tensor_crop_finalize;
151 
159  g_object_class_install_property (object_class, PROP_LATENESS,
160  g_param_spec_int ("lateness", "Lateness",
161  "The time difference between raw and info buffer in milliseconds",
162  -1, G_MAXINT, DEFAULT_LATENESS,
163  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164 
170  g_object_class_install_property (object_class, PROP_SILENT,
171  g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
172  DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
173 
174  element_class->change_state =
175  GST_DEBUG_FUNCPTR (gst_tensor_crop_change_state);
176 
177  gst_element_class_add_pad_template (element_class,
178  gst_static_pad_template_get (&src_template));
179  gst_element_class_add_pad_template (element_class,
180  gst_static_pad_template_get (&raw_template));
181  gst_element_class_add_pad_template (element_class,
182  gst_static_pad_template_get (&info_template));
183 
184  gst_element_class_set_static_metadata (element_class,
185  "TensorCrop",
186  "Filter/Tensor",
187  "Element to crop the regions of incoming tensor",
188  "Samsung Electronics Co., Ltd.");
189 }
190 
194 static void
196 {
199 }
200 
204 static void
206 {
207  GstTensorCropPadData *cpad;
208  GSList *walk;
209 
210  if (self->collect) {
211  walk = self->collect->data;
212 
213  while (walk) {
214  cpad = (GstTensorCropPadData *) walk->data;
215 
217  walk = g_slist_next (walk);
218  }
219  }
220 
221  self->send_stream_start = TRUE;
222 }
223 
227 static void
229 {
230  /* setup sink pad */
231  self->sinkpad_raw = gst_pad_new_from_static_template (&raw_template, "raw");
232  gst_element_add_pad (GST_ELEMENT (self), self->sinkpad_raw);
233 
234  self->sinkpad_info =
235  gst_pad_new_from_static_template (&info_template, "info");
236  gst_element_add_pad (GST_ELEMENT (self), self->sinkpad_info);
237 
238  self->collect = gst_collect_pads_new ();
239  gst_collect_pads_set_function (self->collect,
240  GST_DEBUG_FUNCPTR (gst_tensor_crop_collected), self);
241  gst_collect_pads_set_event_function (self->collect,
242  GST_DEBUG_FUNCPTR (gst_tensor_crop_sink_event), self);
243 
244  gst_collect_pads_add_pad (self->collect, self->sinkpad_raw,
245  sizeof (GstTensorCropPadData), NULL, TRUE);
246  gst_collect_pads_add_pad (self->collect, self->sinkpad_info,
247  sizeof (GstTensorCropPadData), NULL, TRUE);
248 
249  /* setup src pad */
250  self->srcpad = gst_pad_new_from_static_template (&src_template, "src");
251  gst_pad_set_event_function (self->srcpad,
252  GST_DEBUG_FUNCPTR (gst_tensor_crop_src_event));
253  gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
254 
255  /* init properties */
256  self->lateness = DEFAULT_LATENESS;
257  self->silent = DEFAULT_SILENT;
258  self->send_stream_start = TRUE;
259 }
260 
264 static void
265 gst_tensor_crop_finalize (GObject * object)
266 {
267  GstTensorCrop *self;
268 
269  self = GST_TENSOR_CROP (object);
270 
271  gst_tensor_crop_reset (self);
272 
273  if (self->collect) {
274  gst_object_unref (self->collect);
275  self->collect = NULL;
276  }
277 
278  G_OBJECT_CLASS (parent_class)->finalize (object);
279 }
280 
284 static void
285 gst_tensor_crop_set_property (GObject * object, guint prop_id,
286  const GValue * value, GParamSpec * pspec)
287 {
288  GstTensorCrop *self;
289 
290  self = GST_TENSOR_CROP (object);
291 
292  switch (prop_id) {
293  case PROP_LATENESS:
294  self->lateness = g_value_get_int (value);
295  break;
296  case PROP_SILENT:
297  self->silent = g_value_get_boolean (value);
298  break;
299  default:
300  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
301  break;
302  }
303 }
304 
308 static void
309 gst_tensor_crop_get_property (GObject * object, guint prop_id,
310  GValue * value, GParamSpec * pspec)
311 {
312  GstTensorCrop *self;
313 
314  self = GST_TENSOR_CROP (object);
315 
316  switch (prop_id) {
317  case PROP_LATENESS:
318  g_value_set_int (value, self->lateness);
319  break;
320  case PROP_SILENT:
321  g_value_set_boolean (value, self->silent);
322  break;
323  default:
324  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
325  break;
326  }
327 }
328 
332 static GstStateChangeReturn
333 gst_tensor_crop_change_state (GstElement * element, GstStateChange transition)
334 {
335  GstTensorCrop *self;
336  GstStateChangeReturn ret;
337 
338  self = GST_TENSOR_CROP (element);
339 
340  switch (transition) {
341  case GST_STATE_CHANGE_READY_TO_PAUSED:
342  gst_collect_pads_start (self->collect);
343  break;
344  case GST_STATE_CHANGE_PAUSED_TO_READY:
345  gst_collect_pads_stop (self->collect);
346  break;
347  default:
348  break;
349  }
350 
351  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
352 
353  switch (transition) {
354  case GST_STATE_CHANGE_PAUSED_TO_READY:
355  gst_tensor_crop_reset (self);
356  break;
357  default:
358  break;
359  }
360 
361  return ret;
362 }
363 
367 static gboolean
368 gst_tensor_crop_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
369 {
370  g_return_val_if_fail (event != NULL, FALSE);
371 
372  switch (GST_EVENT_TYPE (event)) {
373  case GST_EVENT_SEEK:
374  /* disable seeking */
375  gst_event_unref (event);
376  return FALSE;
377  default:
378  break;
379  }
380 
381  return gst_pad_event_default (pad, parent, event);
382 }
383 
387 static gboolean
388 gst_tensor_crop_sink_event (GstCollectPads * pads, GstCollectData * data,
389  GstEvent * event, gpointer user_data)
390 {
391  GstTensorCropPadData *cpad;
392  UNUSED (user_data);
393 
394  g_return_val_if_fail (event != NULL, FALSE);
395 
396  cpad = (GstTensorCropPadData *) data;
397 
398  switch (GST_EVENT_TYPE (event)) {
399  case GST_EVENT_CAPS:
400  {
401  GstCaps *caps;
402  gboolean ret;
403  gst_event_parse_caps (event, &caps);
404 
405  ret = gst_tensors_config_from_cap (&cpad->config, caps);
406  gst_event_unref (event);
407 
408  return ret;
409  }
410  default:
411  break;
412  }
413 
414  return gst_collect_pads_event_default (pads, data, event, FALSE);
415 }
416 
420 static GstFlowReturn
422 {
423  if (!gst_pad_has_current_caps (self->sinkpad_raw)) {
424  GST_ERROR_OBJECT (self,
425  "The raw pad of tensor_crop '%s' does not have pad caps.",
426  GST_ELEMENT_NAME (self));
427  return GST_FLOW_NOT_NEGOTIATED;
428  }
429 
430  if (!gst_pad_has_current_caps (self->sinkpad_info)) {
431  GST_ERROR_OBJECT (self,
432  "The info pad of tensor_crop '%s' does not have pad caps.",
433  GST_ELEMENT_NAME (self));
434  return GST_FLOW_NOT_NEGOTIATED;
435  }
436 
437  if (!gst_pad_has_current_caps (self->srcpad)) {
438  GstCaps *caps;
439  GstSegment segment;
440  GstTensorsConfig config;
441  GstTensorCropPadData *cpad;
442  GSList *walk;
443 
444  if (self->send_stream_start) {
449  g_autofree gchar *sink_stream_id = gst_pad_get_stream_id (self->sinkpad_raw);
450  g_autofree gchar *element_name = gst_element_get_name (self);
451  g_autofree gchar *pad_name = gst_pad_get_name (self->srcpad);
452  g_autofree gchar *stream_id = g_strdup_printf ("%s-%s-nnscrop-%s-%08x",
453  GST_STR_NULL (sink_stream_id), element_name, pad_name, g_random_int ());
454 
455  gst_pad_push_event (self->srcpad, gst_event_new_stream_start (stream_id));
456  self->send_stream_start = FALSE;
457  }
458 
463  gst_tensors_config_init (&config);
465 
466  walk = self->collect->data;
467  while (walk) {
468  cpad = (GstTensorCropPadData *) walk->data;
469 
470  if (config.rate_n < 0 ||
471  gst_util_fraction_compare (cpad->config.rate_n, cpad->config.rate_d,
472  config.rate_n, config.rate_d) < 0) {
473  config.rate_n = cpad->config.rate_n;
474  config.rate_d = cpad->config.rate_d;
475  }
476 
477  walk = g_slist_next (walk);
478  }
479 
480  caps = gst_tensors_caps_from_config (&config);
481  gst_pad_set_caps (self->srcpad, caps);
482  gst_caps_unref (caps);
483 
484  gst_segment_init (&segment, GST_FORMAT_TIME);
485  gst_pad_push_event (self->srcpad, gst_event_new_segment (&segment));
486  }
487 
488  return GST_FLOW_OK;
489 }
490 
494 static gboolean
496  GstTensorMetaInfo * meta, GstTensorInfo * info, gboolean * is_flexible)
497 {
498  GstCaps *caps;
499  GstStructure *structure;
500  GstTensorsConfig config;
501  GstTensorInfo *_info;
502  gboolean ret = FALSE;
503 
505  gst_tensor_info_init (info);
506 
507  caps = gst_pad_get_current_caps (self->sinkpad_raw);
508  structure = gst_caps_get_structure (caps, 0);
509 
510  if (!gst_tensors_config_from_structure (&config, structure)) {
511  GST_ERROR_OBJECT (self, "Failed to get the config from caps.");
512  goto done;
513  }
514 
518  _info = gst_tensors_info_get_nth_info (&config.info, 0);
519  *is_flexible = gst_tensors_config_is_flexible (&config);
520 
521  if (*is_flexible) {
522  /* meta from buffer */
523  if (gst_tensor_meta_info_parse_header (meta, buffer)) {
524  ret = gst_tensor_meta_info_convert (meta, info);
525  }
526  } else {
527  /* meta from caps */
528  ret = gst_tensor_info_convert_to_meta (_info, meta);
529  gst_tensor_info_copy (info, _info);
530  }
531 
532  /* output is flex tensor */
534 
535 done:
536  gst_caps_unref (caps);
537  gst_tensors_config_free (&config);
538  return ret;
539 }
540 
544 static gboolean
546  tensor_crop_info_s * cinfo)
547 {
548  GstMemory *mem;
549  GstMapInfo map;
550  GstTensorMetaInfo meta;
551  gsize hsize, dsize, esize;
552  guint i, j;
553  guint8 *pos, *src, *desc;
554  gboolean ret = FALSE;
555 
556  i = gst_tensor_buffer_get_count (info);
557  g_assert (i > 0);
558  if (i > 1) {
559  GST_WARNING_OBJECT (self,
560  "Info buffer has %u memories, parse first one.", i);
561  }
562 
563  mem = gst_tensor_buffer_get_nth_memory (info, 0);
564  if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
565  GST_ERROR_OBJECT (self, "Failed to map the info buffer.");
566  goto done;
567  }
568 
569  /* parse crop-info from flex tensor */
570  if (!gst_tensor_meta_info_parse_header (&meta, map.data)) {
571  GST_ERROR_OBJECT (self, "Failed to get the meta from info buffer.");
572  goto done;
573  }
574 
575  hsize = gst_tensor_meta_info_get_header_size (&meta);
576  dsize = gst_tensor_meta_info_get_data_size (&meta);
577  esize = gst_tensor_get_element_size (meta.type);
578 
579  if (hsize + dsize != map.size) {
580  GST_ERROR_OBJECT (self,
581  "Invalid meta info, info buffer size is incorrect (received %zd, expected %zd).",
582  map.size, hsize + dsize);
583  goto done;
584  }
585 
590  g_assert ((dsize % (esize * 4)) == 0);
591 
592  memset (cinfo, 0, sizeof (tensor_crop_info_s));
593 
594  cinfo->num = MIN (dsize / (esize * 4), NNS_TENSOR_SIZE_LIMIT);
595 
596  for (i = 0; i < cinfo->num; i++) {
597  pos = map.data + hsize + (esize * 4 * i);
598 
599  for (j = 0; j < 4; j++) {
600  src = pos + (esize * j);
601  desc = (guint8 *) (&cinfo->region[i]) + sizeof (guint) * j;
602 
603  gst_tensor_data_raw_typecast (src, meta.type, desc, _NNS_UINT32);
604  }
605  }
606 
607  ret = TRUE;
608 
609 done:
610  if (mem) {
611  gst_memory_unmap (mem, &map);
612  gst_memory_unref (mem);
613  }
614 
615  return ret;
616 }
617 
621 static GstBuffer *
623  tensor_crop_info_s * cinfo)
624 {
625  GstBuffer *result = NULL;
626  GstMemory *mem;
627  GstMapInfo map;
628  GstTensorMetaInfo meta;
629  GstTensorInfo info;
630  gboolean flexible;
631  gsize hsize, esize, dsize;
632  guint8 *cropped, *dpos, *desc, *src;
633  guint i, j, ch, mw, mh, _x, _y, _w, _h;
634 
635  i = gst_tensor_buffer_get_count (raw);
636  g_assert (i > 0);
637  if (i > 1) {
638  GST_WARNING_OBJECT (self,
639  "Raw data buffer has %u memories, parse first one.", i);
640  }
641 
642  mem = gst_tensor_buffer_get_nth_memory (raw, 0);
643  if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
644  GST_ERROR_OBJECT (self, "Failed to map the raw buffer.");
645  goto done;
646  }
647 
648  if (!gst_tensor_crop_prepare_out_meta (self, map.data, &meta,
649  &info, &flexible)) {
650  GST_ERROR_OBJECT (self, "Failed to get the output meta.");
651  goto done;
652  }
653 
654  hsize = flexible ? gst_tensor_meta_info_get_header_size (&meta) : 0;
655  dsize = gst_tensor_meta_info_get_data_size (&meta);
656  dpos = map.data + hsize;
657  if ((hsize + dsize) != map.size) {
658  GST_ERROR_OBJECT (self,
659  "Raw buffer has invalid data size (received %zd, expected %zd).",
660  map.size, dsize);
661  goto done;
662  }
663 
664  result = gst_buffer_new ();
665 
667  ch = info.dimension[0];
668  mw = info.dimension[1];
669  mh = info.dimension[2];
670  esize = gst_tensor_get_element_size (info.type);
671  hsize = gst_tensor_meta_info_get_header_size (&meta);
672 
673  for (i = 0; i < cinfo->num; i++) {
674  GstTensorInfo crop_info;
675  GstMemory *crop_mem;
676 
677  _x = (cinfo->region[i].x < mw) ? cinfo->region[i].x : mw;
678  _y = (cinfo->region[i].y < mh) ? cinfo->region[i].y : mh;
679  _w = (_x + cinfo->region[i].w - 1 < mw) ? cinfo->region[i].w : (mw - _x);
680  _h = (_y + cinfo->region[i].h - 1 < mh) ? cinfo->region[i].h : (mh - _y);
681 
682  g_assert (_w > 0 && _h > 0);
683  dsize = hsize + (esize * ch * _w * _h);
684  cropped = (guint8 *) g_malloc0 (dsize);
685 
686  /* set header for flex tensor */
687  meta.dimension[1] = _w;
688  meta.dimension[2] = _h;
689  meta.dimension[3] = 1;
690  gst_tensor_meta_info_update_header (&meta, cropped);
691 
692  for (j = 0; j < _h; j++) {
693  src = dpos + esize * ch * (_x + (j + _y) * mw);
694  desc = cropped + hsize + (esize * ch * _w) * j;
695  memcpy (desc, src, (esize * ch * _w));
696  }
697 
698  /* Prepare tensors-info to append memory into gst-buffer. */
699  gst_tensor_meta_info_convert (&meta, &crop_info);
700  crop_mem =
701  gst_memory_new_wrapped (0, cropped, dsize, 0, dsize, cropped, g_free);
702 
703  gst_tensor_buffer_append_memory (result, crop_mem, &crop_info);
704  gst_tensor_info_free (&crop_info);
705  }
706 
707  /* set timestamp from raw buffer */
708  gst_buffer_copy_into (result, raw, GST_BUFFER_COPY_METADATA, 0, -1);
709 
710 done:
711  if (mem) {
712  gst_memory_unmap (mem, &map);
713  gst_memory_unref (mem);
714  }
715 
716  return result;
717 }
718 
722 static GstFlowReturn
724  GstCollectData * data_raw, GstCollectData * data_info)
725 {
726  GstFlowReturn ret;
727  GstBuffer *buf_raw, *buf_info, *result;
728  GstTensorCropPadData *cpad;
729  tensor_crop_info_s cinfo;
730  gboolean drop_raw, drop_info;
731 
732  g_return_val_if_fail (data_raw && data_info, GST_FLOW_ERROR);
733 
734  buf_raw = gst_collect_pads_peek (self->collect, data_raw);
735  buf_info = gst_collect_pads_peek (self->collect, data_info);
736  drop_raw = (buf_raw != NULL);
737  drop_info = (buf_info != NULL);
738 
739  if (!buf_raw || !buf_info) {
740  ret = GST_FLOW_EOS;
741  goto done;
742  }
743 
744  cpad = (GstTensorCropPadData *) data_raw;
745  buf_raw = gst_tensor_buffer_from_config (buf_raw, &cpad->config);
746  cpad = (GstTensorCropPadData *) data_info;
747  buf_info = gst_tensor_buffer_from_config (buf_info, &cpad->config);
748 
753  if (self->lateness >= 0) {
754  GstClockTime ts_raw, ts_info, lateness;
755 
756  ts_raw = GST_BUFFER_TIMESTAMP (buf_raw);
757  ts_info = GST_BUFFER_TIMESTAMP (buf_info);
758  lateness = self->lateness * GST_MSECOND;
759 
760  if (GST_CLOCK_TIME_IS_VALID (ts_raw) && GST_CLOCK_TIME_IS_VALID (ts_info)) {
761  if (((GstClockTime) ABS (GST_CLOCK_DIFF (ts_raw, ts_info))) > lateness) {
762  GST_DEBUG_OBJECT (self, "Drop old buffer and wait for next.");
763  GST_DEBUG_OBJECT (self, "Raw buffer ts: %" GST_TIME_FORMAT,
764  GST_TIME_ARGS (ts_raw));
765  GST_DEBUG_OBJECT (self, "Info buffer ts: %" GST_TIME_FORMAT,
766  GST_TIME_ARGS (ts_info));
767 
768  /* clear old buffer and return ok to get next buffer */
769  if (ts_raw > ts_info)
770  drop_raw = FALSE;
771  else
772  drop_info = FALSE;
773 
774  ret = GST_FLOW_OK;
775  goto done;
776  }
777  } else {
778  GST_WARNING_OBJECT (self,
779  "Incoming buffer has invalid timestamp, continue cropping data.");
780  }
781  }
782 
783  if (!gst_tensor_crop_get_crop_info (self, buf_info, &cinfo)) {
784  ret = GST_FLOW_ERROR;
785  goto done;
786  }
787 
788  result = gst_tensor_crop_do_cropping (self, buf_raw, &cinfo);
789  ret = gst_pad_push (self->srcpad, result);
790 
791 done:
792  if (buf_raw)
793  gst_buffer_unref (buf_raw);
794  if (buf_info)
795  gst_buffer_unref (buf_info);
796 
797  /* clear buffer in collect pads */
798  if (drop_raw)
799  gst_buffer_unref (gst_collect_pads_pop (self->collect, data_raw));
800  if (drop_info)
801  gst_buffer_unref (gst_collect_pads_pop (self->collect, data_info));
802 
803  return ret;
804 }
805 
809 static GstFlowReturn
810 gst_tensor_crop_collected (GstCollectPads * pads, gpointer user_data)
811 {
812  GstTensorCrop *self;
813  GstCollectData *data_raw, *data_info;
814  GSList *walk;
815  GstFlowReturn ret;
816 
817  self = GST_TENSOR_CROP (user_data);
818  data_raw = data_info = NULL;
819 
820  ret = gst_tensor_crop_negotiate (self);
821  if (ret != GST_FLOW_OK)
822  return ret;
823 
824  for (walk = pads->data; walk; walk = g_slist_next (walk)) {
825  GstCollectData *data;
826 
827  data = (GstCollectData *) walk->data;
828 
829  if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_EOS)) {
830  gst_pad_push_event (self->srcpad, gst_event_new_eos ());
831  return GST_FLOW_EOS;
832  }
833 
834  if (data->pad == self->sinkpad_raw) {
835  data_raw = data;
836  } else if (data->pad == self->sinkpad_info) {
837  data_info = data;
838  }
839  }
840 
841  return gst_tensor_crop_chain (self, data_raw, data_info);
842 }
gst_tensor_crop_class_init
static void gst_tensor_crop_class_init(GstTensorCropClass *klass)
Initialize the tensor_crop's class.
Definition: gsttensor_crop.c:137
GstTensorCropPadData::data
GstCollectData data
Definition: gsttensor_crop.h:41
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
gst_tensor_crop_change_state
static GstStateChangeReturn gst_tensor_crop_change_state(GstElement *element, GstStateChange transition)
Handle state transition.
Definition: gsttensor_crop.c:333
g_assert
g_assert(sizeof(DTYPE_UNSIGNED)==sizeof(DTYPE_SIGNED))
tensor_crop_info_s::region
tensor_region_s region[NNS_TENSOR_SIZE_LIMIT]
Definition: gsttensor_crop.c:65
tensor_region_s
Internal data structure to describe tensor region.
Definition: gsttensor_crop.c:50
tensor_data.h
Internal functions to handle various tensor type and value.
tensor_region_s::y
guint y
Definition: gsttensor_crop.c:53
data
svtc_1 data
Definition: gsttensor_if.c:826
GstTensorInfo
Internal data structure for tensor info.
Definition: tensor_typedef.h:261
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_tensor_crop_reset
static void gst_tensor_crop_reset(GstTensorCrop *self)
Clear and reset old data in tensor_crop.
Definition: gsttensor_crop.c:205
FALSE
return FALSE
Definition: gsttensor_transform.c:596
result
case tensor_data_s gboolean * result
Definition: gsttensor_if.c:821
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_crop_init
static void gst_tensor_crop_init(GstTensorCrop *self)
Initialize tensor_crop element.
Definition: gsttensor_crop.c:228
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_crop.c:78
gst_tensor_crop_chain
static GstFlowReturn gst_tensor_crop_chain(GstTensorCrop *self, GstCollectData *data_raw, GstCollectData *data_info)
Internal function to transform the input buffer.
Definition: gsttensor_crop.c:723
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
gst_tensor_crop_do_cropping
static GstBuffer * gst_tensor_crop_do_cropping(GstTensorCrop *self, GstBuffer *raw, tensor_crop_info_s *cinfo)
Internal function to crop incoming buffer.
Definition: gsttensor_crop.c:622
info_template
static GstStaticPadTemplate info_template
Template for sink pad (crop info).
Definition: gsttensor_crop.c:103
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
GstTensorMetaInfo::type
uint32_t type
Definition: tensor_typedef.h:314
PROP_LATENESS
@ PROP_LATENESS
Definition: gsttensor_crop.c:77
GstTensorsConfig::rate_d
int rate_d
Definition: tensor_typedef.h:288
src_template
static GstStaticPadTemplate src_template
Template for src pad.
Definition: gsttensor_crop.c:111
gst_tensor_crop_src_event
static gboolean gst_tensor_crop_src_event(GstPad *pad, GstObject *parent, GstEvent *event)
Handle event on src pad.
Definition: gsttensor_crop.c:368
_GstTensorCropClass
GstTensorCropClass data structure.
Definition: gsttensor_crop.h:67
g_free
g_free(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
tensor_crop_info_s
Internal data structure to describe cropping tensor data.
Definition: gsttensor_crop.c:62
GstTensorsConfig::rate_n
int rate_n
Definition: tensor_typedef.h:287
_NNS_TENSOR_FORMAT_FLEXIBLE
@ _NNS_TENSOR_FORMAT_FLEXIBLE
Definition: tensor_typedef.h:196
gst_tensor_crop_set_property
static void gst_tensor_crop_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
Setter for tensor_crop properties.
Definition: gsttensor_crop.c:285
gst_tensor_get_element_size
gsize gst_tensor_get_element_size(tensor_type type)
Get element size of tensor type (byte per element)
Definition: nnstreamer_plugin_api_util_impl.c:1205
gst_tensor_data_raw_typecast
gboolean gst_tensor_data_raw_typecast(gpointer input, tensor_type in_type, gpointer output, tensor_type out_type)
Typecast tensor element value.
Definition: tensor_data.c:290
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_crop_sink_event
static gboolean gst_tensor_crop_sink_event(GstCollectPads *pads, GstCollectData *data, GstEvent *event, gpointer user_data)
Handle event on sink pad.
Definition: gsttensor_crop.c:388
raw_template
static GstStaticPadTemplate raw_template
Template for sink pad (raw data).
Definition: gsttensor_crop.c:94
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_CROP
#define GST_TENSOR_CROP(obj)
Definition: gsttensor_crop.h:24
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_crop_finalize
static void gst_tensor_crop_finalize(GObject *object)
Function to finalize instance.
Definition: gsttensor_crop.c:265
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
GstTensorMetaInfo::dimension
tensor_dim dimension
Definition: tensor_typedef.h:315
DEFAULT_LATENESS
#define DEFAULT_LATENESS
Default value to compare timestamp of raw and info buffer, in milliseconds (-1 means no synchronizati...
Definition: gsttensor_crop.c:89
TRUE
return TRUE
Definition: gsttensor_if.c:879
UNUSED
#define UNUSED(expr)
Definition: mqttcommon.h:19
tensor_region_s::x
guint x
Definition: gsttensor_crop.c:52
nnstreamer_util.h
Optional NNStreamer utility functions for sub-plugin writers and users.
tensor_region_s::h
guint h
Definition: gsttensor_crop.c:55
gst_tensor_info_free
void gst_tensor_info_free(GstTensorInfo *info)
Free allocated data in tensor info structure.
Definition: nnstreamer_plugin_api_util_impl.c:140
gst_tensor_crop_collected
static GstFlowReturn gst_tensor_crop_collected(GstCollectPads *pads, gpointer user_data)
Chain function called when the buffer is available on all of the collect pads.
Definition: gsttensor_crop.c:810
tensor_crop_info_s::num
guint num
Definition: gsttensor_crop.c:64
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
GST_TENSORS_CAP_MAKE
#define GST_TENSORS_CAP_MAKE(fmt)
Caps string for the caps template of tensor stream. format should be a string that describes the data...
Definition: tensor_typedef.h:97
GST_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensor_crop_debug)
gst_tensor_crop_get_property
static void gst_tensor_crop_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
Getter for tensor_crop properties.
Definition: gsttensor_crop.c:309
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_tensors_config_from_cap
gboolean gst_tensors_config_from_cap(GstTensorsConfig *config, const GstCaps *caps)
Parse caps and set tensors config (for other/tensors)
Definition: nnstreamer_plugin_api_impl.c:1509
PROP_0
@ PROP_0
Definition: gsttensor_crop.c:76
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorCrop, gst_tensor_crop, GST_TYPE_ELEMENT)
DEFAULT_SILENT
#define DEFAULT_SILENT
Flag to print minimized log.
Definition: gsttensor_crop.c:84
GstTensorMetaInfo::format
uint32_t format
Definition: tensor_typedef.h:316
gst_tensor_crop_prepare_out_meta
static gboolean gst_tensor_crop_prepare_out_meta(GstTensorCrop *self, gpointer buffer, GstTensorMetaInfo *meta, GstTensorInfo *info, gboolean *is_flexible)
Internal function to prepare output meta info.
Definition: gsttensor_crop.c:495
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:1608
gsttensor_crop.h
GStreamer element to crop the regions of incoming tensor.
gst_tensors_config_init
void gst_tensors_config_init(GstTensorsConfig *config)
Initialize the tensors config info structure (for other/tensors)
Definition: nnstreamer_plugin_api_util_impl.c:830
gst_tensor_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:1835
GstTensorCropPadData::config
GstTensorsConfig config
Definition: gsttensor_crop.h:43
GstTensorInfo::type
tensor_type type
Definition: tensor_typedef.h:266
GstTensorsConfig::info
GstTensorsInfo info
Definition: tensor_typedef.h:286
_NNS_UINT32
@ _NNS_UINT32
Definition: tensor_typedef.h:141
GstTensorInfo::dimension
tensor_dim dimension
Definition: tensor_typedef.h:267
gst_tensors_config_from_structure
gboolean gst_tensors_config_from_structure(GstTensorsConfig *config, const GstStructure *structure)
Parse structure and set tensors config (for other/tensors)
Definition: nnstreamer_plugin_api_impl.c:1413
tensor_region_s::w
guint w
Definition: gsttensor_crop.c:54
_GstTensorCrop
GstTensorCrop data structure.
Definition: gsttensor_crop.h:49
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_tensor_crop_pad_reset
static void gst_tensor_crop_pad_reset(GstTensorCropPadData *cpad)
Clear and reset old pad data.
Definition: gsttensor_crop.c:195
if
if(!gst_tensordec_process_plugin_options(self,(opnum) - 1)) GST_ERROR_OBJECT(self
gst_tensor_crop_negotiate
static GstFlowReturn gst_tensor_crop_negotiate(GstTensorCrop *self)
Set pad caps if not negotiated.
Definition: gsttensor_crop.c:421
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:1688
GstTensorsInfo::format
tensor_format format
Definition: tensor_typedef.h:278
gst_tensor_crop_get_crop_info
static gboolean gst_tensor_crop_get_crop_info(GstTensorCrop *self, GstBuffer *info, tensor_crop_info_s *cinfo)
Internal function to parse buffer and fill crop info.
Definition: gsttensor_crop.c:545
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
GstTensorCropPadData
GstTensorCrop pad data.
Definition: gsttensor_crop.h:39