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  GstStructure *structure;
403 
404  gst_event_parse_caps (event, &caps);
405  structure = gst_caps_get_structure (caps, 0);
406 
407  gst_tensors_config_from_structure (&cpad->config, structure);
408 
409  gst_event_unref (event);
410  return gst_tensors_config_validate (&cpad->config);
411  }
412  default:
413  break;
414  }
415 
416  return gst_collect_pads_event_default (pads, data, event, FALSE);
417 }
418 
422 static GstFlowReturn
424 {
425  if (!gst_pad_has_current_caps (self->sinkpad_raw)) {
426  GST_ERROR_OBJECT (self,
427  "The raw pad of tensor_crop '%s' does not have pad caps.",
428  GST_ELEMENT_NAME (self));
429  return GST_FLOW_NOT_NEGOTIATED;
430  }
431 
432  if (!gst_pad_has_current_caps (self->sinkpad_info)) {
433  GST_ERROR_OBJECT (self,
434  "The info pad of tensor_crop '%s' does not have pad caps.",
435  GST_ELEMENT_NAME (self));
436  return GST_FLOW_NOT_NEGOTIATED;
437  }
438 
439  if (!gst_pad_has_current_caps (self->srcpad)) {
440  GstCaps *caps;
441  GstSegment segment;
442  GstTensorsConfig config;
443  GstTensorCropPadData *cpad;
444  GSList *walk;
445 
446  if (self->send_stream_start) {
451  g_autofree gchar *sink_stream_id = gst_pad_get_stream_id (self->sinkpad_raw);
452  g_autofree gchar *element_name = gst_element_get_name (self);
453  g_autofree gchar *pad_name = gst_pad_get_name (self->srcpad);
454  g_autofree gchar *stream_id = g_strdup_printf ("%s-%s-nnscrop-%s-%08x",
455  GST_STR_NULL (sink_stream_id), element_name, pad_name, g_random_int ());
456 
457  gst_pad_push_event (self->srcpad, gst_event_new_stream_start (stream_id));
458  self->send_stream_start = FALSE;
459  }
460 
465  gst_tensors_config_init (&config);
467 
468  walk = self->collect->data;
469  while (walk) {
470  cpad = (GstTensorCropPadData *) walk->data;
471 
472  if (config.rate_n < 0 ||
473  gst_util_fraction_compare (cpad->config.rate_n, cpad->config.rate_d,
474  config.rate_n, config.rate_d) < 0) {
475  config.rate_n = cpad->config.rate_n;
476  config.rate_d = cpad->config.rate_d;
477  }
478 
479  walk = g_slist_next (walk);
480  }
481 
482  caps = gst_tensors_caps_from_config (&config);
483  gst_pad_set_caps (self->srcpad, caps);
484  gst_caps_unref (caps);
485 
486  gst_segment_init (&segment, GST_FORMAT_TIME);
487  gst_pad_push_event (self->srcpad, gst_event_new_segment (&segment));
488  }
489 
490  return GST_FLOW_OK;
491 }
492 
496 static gboolean
498  GstTensorMetaInfo * meta, GstTensorInfo * info, gboolean * is_flexible)
499 {
500  GstCaps *caps;
501  GstStructure *structure;
502  GstTensorsConfig config;
503  GstTensorInfo *_info;
504  gboolean ret = FALSE;
505 
507  gst_tensor_info_init (info);
508 
509  caps = gst_pad_get_current_caps (self->sinkpad_raw);
510  structure = gst_caps_get_structure (caps, 0);
511 
512  if (!gst_tensors_config_from_structure (&config, structure)) {
513  GST_ERROR_OBJECT (self, "Failed to get the config from caps.");
514  goto done;
515  }
516 
520  _info = gst_tensors_info_get_nth_info (&config.info, 0);
521  *is_flexible = gst_tensors_config_is_flexible (&config);
522 
523  if (*is_flexible) {
524  /* meta from buffer */
525  if (gst_tensor_meta_info_parse_header (meta, buffer)) {
526  ret = gst_tensor_meta_info_convert (meta, info);
527  }
528  } else {
529  /* meta from caps */
530  ret = gst_tensor_info_convert_to_meta (_info, meta);
531  gst_tensor_info_copy (info, _info);
532  }
533 
534  /* output is flex tensor */
536 
537 done:
538  gst_caps_unref (caps);
539  gst_tensors_config_free (&config);
540  return ret;
541 }
542 
546 static gboolean
548  tensor_crop_info_s * cinfo)
549 {
550  GstMemory *mem;
551  GstMapInfo map;
552  GstTensorMetaInfo meta;
553  gsize hsize, dsize, esize;
554  guint i, j;
555  guint8 *pos, *src, *desc;
556  gboolean ret = FALSE;
557 
558  i = gst_tensor_buffer_get_count (info);
559  g_assert (i > 0);
560  if (i > 1) {
561  GST_WARNING_OBJECT (self,
562  "Info buffer has %u memories, parse first one.", i);
563  }
564 
565  mem = gst_tensor_buffer_get_nth_memory (info, 0);
566  if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
567  GST_ERROR_OBJECT (self, "Failed to map the info buffer.");
568  goto done;
569  }
570 
571  /* parse crop-info from flex tensor */
572  if (!gst_tensor_meta_info_parse_header (&meta, map.data)) {
573  GST_ERROR_OBJECT (self, "Failed to get the meta from info buffer.");
574  goto done;
575  }
576 
577  hsize = gst_tensor_meta_info_get_header_size (&meta);
578  dsize = gst_tensor_meta_info_get_data_size (&meta);
579  esize = gst_tensor_get_element_size (meta.type);
580 
581  if (hsize + dsize != map.size) {
582  GST_ERROR_OBJECT (self,
583  "Invalid meta info, info buffer size is incorrect (received %zd, expected %zd).",
584  map.size, hsize + dsize);
585  goto done;
586  }
587 
592  g_assert ((dsize % (esize * 4)) == 0);
593 
594  memset (cinfo, 0, sizeof (tensor_crop_info_s));
595 
596  cinfo->num = MIN (dsize / (esize * 4), NNS_TENSOR_SIZE_LIMIT);
597 
598  for (i = 0; i < cinfo->num; i++) {
599  pos = map.data + hsize + (esize * 4 * i);
600 
601  for (j = 0; j < 4; j++) {
602  src = pos + (esize * j);
603  desc = (guint8 *) (&cinfo->region[i]) + sizeof (guint) * j;
604 
605  gst_tensor_data_raw_typecast (src, meta.type, desc, _NNS_UINT32);
606  }
607  }
608 
609  ret = TRUE;
610 
611 done:
612  if (mem) {
613  gst_memory_unmap (mem, &map);
614  gst_memory_unref (mem);
615  }
616 
617  return ret;
618 }
619 
623 static GstBuffer *
625  tensor_crop_info_s * cinfo)
626 {
627  GstBuffer *result = NULL;
628  GstMemory *mem;
629  GstMapInfo map;
630  GstTensorMetaInfo meta;
631  GstTensorInfo info;
632  gboolean flexible;
633  gsize hsize, esize, dsize;
634  guint8 *cropped, *dpos, *desc, *src;
635  guint i, j, ch, mw, mh, _x, _y, _w, _h;
636 
637  i = gst_tensor_buffer_get_count (raw);
638  g_assert (i > 0);
639  if (i > 1) {
640  GST_WARNING_OBJECT (self,
641  "Raw data buffer has %u memories, parse first one.", i);
642  }
643 
644  mem = gst_tensor_buffer_get_nth_memory (raw, 0);
645  if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
646  GST_ERROR_OBJECT (self, "Failed to map the raw buffer.");
647  goto done;
648  }
649 
650  if (!gst_tensor_crop_prepare_out_meta (self, map.data, &meta,
651  &info, &flexible)) {
652  GST_ERROR_OBJECT (self, "Failed to get the output meta.");
653  goto done;
654  }
655 
656  hsize = flexible ? gst_tensor_meta_info_get_header_size (&meta) : 0;
657  dsize = gst_tensor_meta_info_get_data_size (&meta);
658  dpos = map.data + hsize;
659  if ((hsize + dsize) != map.size) {
660  GST_ERROR_OBJECT (self,
661  "Raw buffer has invalid data size (received %zd, expected %zd).",
662  map.size, dsize);
663  goto done;
664  }
665 
666  result = gst_buffer_new ();
667 
669  ch = info.dimension[0];
670  mw = info.dimension[1];
671  mh = info.dimension[2];
672  esize = gst_tensor_get_element_size (info.type);
673  hsize = gst_tensor_meta_info_get_header_size (&meta);
674 
675  for (i = 0; i < cinfo->num; i++) {
676  GstTensorInfo crop_info;
677  GstMemory *crop_mem;
678 
679  _x = (cinfo->region[i].x < mw) ? cinfo->region[i].x : mw;
680  _y = (cinfo->region[i].y < mh) ? cinfo->region[i].y : mh;
681  _w = (_x + cinfo->region[i].w - 1 < mw) ? cinfo->region[i].w : (mw - _x);
682  _h = (_y + cinfo->region[i].h - 1 < mh) ? cinfo->region[i].h : (mh - _y);
683 
684  g_assert (_w > 0 && _h > 0);
685  dsize = hsize + (esize * ch * _w * _h);
686  cropped = (guint8 *) g_malloc0 (dsize);
687 
688  /* set header for flex tensor */
689  meta.dimension[1] = _w;
690  meta.dimension[2] = _h;
691  meta.dimension[3] = 1;
692  gst_tensor_meta_info_update_header (&meta, cropped);
693 
694  for (j = 0; j < _h; j++) {
695  src = dpos + esize * ch * (_x + (j + _y) * mw);
696  desc = cropped + hsize + (esize * ch * _w) * j;
697  memcpy (desc, src, (esize * ch * _w));
698  }
699 
700  /* Prepare tensors-info to append memory into gst-buffer. */
701  gst_tensor_meta_info_convert (&meta, &crop_info);
702  crop_mem =
703  gst_memory_new_wrapped (0, cropped, dsize, 0, dsize, cropped, g_free);
704 
705  gst_tensor_buffer_append_memory (result, crop_mem, &crop_info);
706  gst_tensor_info_free (&crop_info);
707  }
708 
709  /* set timestamp from raw buffer */
710  gst_buffer_copy_into (result, raw, GST_BUFFER_COPY_METADATA, 0, -1);
711 
712 done:
713  if (mem) {
714  gst_memory_unmap (mem, &map);
715  gst_memory_unref (mem);
716  }
717 
718  return result;
719 }
720 
724 static GstFlowReturn
726  GstCollectData * data_raw, GstCollectData * data_info)
727 {
728  GstFlowReturn ret;
729  GstBuffer *buf_raw, *buf_info, *result;
730  GstTensorCropPadData *cpad;
731  tensor_crop_info_s cinfo;
732  gboolean drop_raw, drop_info;
733 
734  g_return_val_if_fail (data_raw && data_info, GST_FLOW_ERROR);
735 
736  buf_raw = gst_collect_pads_peek (self->collect, data_raw);
737  buf_info = gst_collect_pads_peek (self->collect, data_info);
738  drop_raw = (buf_raw != NULL);
739  drop_info = (buf_info != NULL);
740 
741  if (!buf_raw || !buf_info) {
742  ret = GST_FLOW_EOS;
743  goto done;
744  }
745 
746  cpad = (GstTensorCropPadData *) data_raw;
747  buf_raw = gst_tensor_buffer_from_config (buf_raw, &cpad->config);
748  cpad = (GstTensorCropPadData *) data_info;
749  buf_info = gst_tensor_buffer_from_config (buf_info, &cpad->config);
750 
755  if (self->lateness >= 0) {
756  GstClockTime ts_raw, ts_info, lateness;
757 
758  ts_raw = GST_BUFFER_TIMESTAMP (buf_raw);
759  ts_info = GST_BUFFER_TIMESTAMP (buf_info);
760  lateness = self->lateness * GST_MSECOND;
761 
762  if (GST_CLOCK_TIME_IS_VALID (ts_raw) && GST_CLOCK_TIME_IS_VALID (ts_info)) {
763  if (((GstClockTime) ABS (GST_CLOCK_DIFF (ts_raw, ts_info))) > lateness) {
764  GST_DEBUG_OBJECT (self, "Drop old buffer and wait for next.");
765  GST_DEBUG_OBJECT (self, "Raw buffer ts: %" GST_TIME_FORMAT,
766  GST_TIME_ARGS (ts_raw));
767  GST_DEBUG_OBJECT (self, "Info buffer ts: %" GST_TIME_FORMAT,
768  GST_TIME_ARGS (ts_info));
769 
770  /* clear old buffer and return ok to get next buffer */
771  if (ts_raw > ts_info)
772  drop_raw = FALSE;
773  else
774  drop_info = FALSE;
775 
776  ret = GST_FLOW_OK;
777  goto done;
778  }
779  } else {
780  GST_WARNING_OBJECT (self,
781  "Incoming buffer has invalid timestamp, continue cropping data.");
782  }
783  }
784 
785  if (!gst_tensor_crop_get_crop_info (self, buf_info, &cinfo)) {
786  ret = GST_FLOW_ERROR;
787  goto done;
788  }
789 
790  result = gst_tensor_crop_do_cropping (self, buf_raw, &cinfo);
791  ret = gst_pad_push (self->srcpad, result);
792 
793 done:
794  if (buf_raw)
795  gst_buffer_unref (buf_raw);
796  if (buf_info)
797  gst_buffer_unref (buf_info);
798 
799  /* clear buffer in collect pads */
800  if (drop_raw)
801  gst_buffer_unref (gst_collect_pads_pop (self->collect, data_raw));
802  if (drop_info)
803  gst_buffer_unref (gst_collect_pads_pop (self->collect, data_info));
804 
805  return ret;
806 }
807 
811 static GstFlowReturn
812 gst_tensor_crop_collected (GstCollectPads * pads, gpointer user_data)
813 {
814  GstTensorCrop *self;
815  GstCollectData *data_raw, *data_info;
816  GSList *walk;
817  GstFlowReturn ret;
818 
819  self = GST_TENSOR_CROP (user_data);
820  data_raw = data_info = NULL;
821 
822  ret = gst_tensor_crop_negotiate (self);
823  if (ret != GST_FLOW_OK)
824  return ret;
825 
826  for (walk = pads->data; walk; walk = g_slist_next (walk)) {
827  GstCollectData *data;
828 
829  data = (GstCollectData *) walk->data;
830 
831  if (GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_EOS)) {
832  gst_pad_push_event (self->srcpad, gst_event_new_eos ());
833  return GST_FLOW_EOS;
834  }
835 
836  if (data->pad == self->sinkpad_raw) {
837  data_raw = data;
838  } else if (data->pad == self->sinkpad_info) {
839  data_info = data;
840  }
841  }
842 
843  return gst_tensor_crop_chain (self, data_raw, data_info);
844 }
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:844
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:590
result
case tensor_data_s gboolean * result
Definition: gsttensor_if.c:839
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:725
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:624
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:897
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:812
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
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:497
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
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:1813
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
gst_tensors_config_validate
gboolean gst_tensors_config_validate(const GstTensorsConfig *config)
Check the tensors are all configured (for other/tensors)
Definition: nnstreamer_plugin_api_util_impl.c:858
_NNS_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:423
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
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:547
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