69 #define GST_CAT_DEFAULT gst_tensor_crop_debug
84 #define DEFAULT_SILENT TRUE
89 #define DEFAULT_LATENESS (-1)
94 static GstStaticPadTemplate
raw_template = GST_STATIC_PAD_TEMPLATE (
"raw",
103 static GstStaticPadTemplate
info_template = GST_STATIC_PAD_TEMPLATE (
"info",
111 static GstStaticPadTemplate
src_template = GST_STATIC_PAD_TEMPLATE (
"src",
116 #define gst_tensor_crop_parent_class parent_class
121 const GValue * value, GParamSpec * pspec);
123 GValue * value, GParamSpec * pspec);
125 GstStateChange transition);
129 GstCollectData *
data, GstEvent * event, gpointer user_data);
139 GObjectClass *object_class;
140 GstElementClass *element_class;
142 GST_DEBUG_CATEGORY_INIT (gst_tensor_crop_debug,
"tensor_crop", 0,
143 "Element to crop the regions of incoming tensor");
145 object_class = (GObjectClass *) klass;
146 element_class = (GstElementClass *) klass;
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",
163 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
170 g_object_class_install_property (object_class,
PROP_SILENT,
171 g_param_spec_boolean (
"silent",
"Silent",
"Produce verbose output",
174 element_class->change_state =
177 gst_element_class_add_pad_template (element_class,
179 gst_element_class_add_pad_template (element_class,
181 gst_element_class_add_pad_template (element_class,
184 gst_element_class_set_static_metadata (element_class,
187 "Element to crop the regions of incoming tensor",
188 "Samsung Electronics Co., Ltd.");
211 walk =
self->collect->
data;
217 walk = g_slist_next (walk);
221 self->send_stream_start =
TRUE;
231 self->sinkpad_raw = gst_pad_new_from_static_template (&
raw_template,
"raw");
232 gst_element_add_pad (GST_ELEMENT (
self), self->sinkpad_raw);
236 gst_element_add_pad (GST_ELEMENT (
self), self->sinkpad_info);
238 self->collect = gst_collect_pads_new ();
239 gst_collect_pads_set_function (self->collect,
241 gst_collect_pads_set_event_function (self->collect,
244 gst_collect_pads_add_pad (self->collect, self->sinkpad_raw,
246 gst_collect_pads_add_pad (self->collect, self->sinkpad_info,
250 self->srcpad = gst_pad_new_from_static_template (&
src_template,
"src");
251 gst_pad_set_event_function (self->srcpad,
253 gst_element_add_pad (GST_ELEMENT (
self), self->srcpad);
258 self->send_stream_start =
TRUE;
274 gst_object_unref (self->collect);
275 self->collect = NULL;
278 G_OBJECT_CLASS (parent_class)->finalize (
object);
286 const GValue * value, GParamSpec * pspec)
294 self->lateness = g_value_get_int (value);
297 self->silent = g_value_get_boolean (value);
300 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
310 GValue * value, GParamSpec * pspec)
318 g_value_set_int (value, self->lateness);
321 g_value_set_boolean (value, self->silent);
324 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
332 static GstStateChangeReturn
336 GstStateChangeReturn ret;
340 switch (transition) {
341 case GST_STATE_CHANGE_READY_TO_PAUSED:
342 gst_collect_pads_start (self->collect);
344 case GST_STATE_CHANGE_PAUSED_TO_READY:
345 gst_collect_pads_stop (self->collect);
351 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
353 switch (transition) {
354 case GST_STATE_CHANGE_PAUSED_TO_READY:
370 g_return_val_if_fail (event != NULL,
FALSE);
372 switch (GST_EVENT_TYPE (event)) {
375 gst_event_unref (event);
381 return gst_pad_event_default (pad, parent, event);
389 GstEvent * event, gpointer user_data)
394 g_return_val_if_fail (event != NULL,
FALSE);
398 switch (GST_EVENT_TYPE (event)) {
402 GstStructure *structure;
404 gst_event_parse_caps (event, &caps);
405 structure = gst_caps_get_structure (caps, 0);
409 gst_event_unref (event);
416 return gst_collect_pads_event_default (pads,
data, event,
FALSE);
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;
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;
439 if (!gst_pad_has_current_caps (self->srcpad)) {
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 ());
457 gst_pad_push_event (self->srcpad, gst_event_new_stream_start (stream_id));
458 self->send_stream_start =
FALSE;
468 walk =
self->collect->data;
479 walk = g_slist_next (walk);
483 gst_pad_set_caps (self->srcpad, caps);
484 gst_caps_unref (caps);
486 gst_segment_init (&segment, GST_FORMAT_TIME);
487 gst_pad_push_event (self->srcpad, gst_event_new_segment (&segment));
501 GstStructure *structure;
504 gboolean ret =
FALSE;
509 caps = gst_pad_get_current_caps (self->sinkpad_raw);
510 structure = gst_caps_get_structure (caps, 0);
513 GST_ERROR_OBJECT (
self,
"Failed to get the config from caps.");
538 gst_caps_unref (caps);
553 gsize hsize, dsize, esize;
555 guint8 *pos, *src, *desc;
556 gboolean ret =
FALSE;
561 GST_WARNING_OBJECT (
self,
562 "Info buffer has %u memories, parse first one.", i);
566 if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
567 GST_ERROR_OBJECT (
self,
"Failed to map the info buffer.");
573 GST_ERROR_OBJECT (
self,
"Failed to get the meta from info buffer.");
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);
592 g_assert ((dsize % (esize * 4)) == 0);
598 for (i = 0; i < cinfo->
num; i++) {
599 pos = map.data + hsize + (esize * 4 * i);
601 for (j = 0; j < 4; j++) {
602 src = pos + (esize * j);
603 desc = (guint8 *) (&cinfo->
region[i]) +
sizeof (guint) * j;
613 gst_memory_unmap (mem, &map);
614 gst_memory_unref (mem);
633 gsize hsize, esize, dsize;
634 guint8 *cropped, *dpos, *desc, *src;
635 guint i, j, ch, mw, mh, _x, _y, _w, _h;
640 GST_WARNING_OBJECT (
self,
641 "Raw data buffer has %u memories, parse first one.", i);
645 if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
646 GST_ERROR_OBJECT (
self,
"Failed to map the raw buffer.");
652 GST_ERROR_OBJECT (
self,
"Failed to get the output 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).",
666 result = gst_buffer_new ();
675 for (i = 0; i < cinfo->
num; i++) {
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);
685 dsize = hsize + (esize * ch * _w * _h);
686 cropped = (guint8 *) g_malloc0 (dsize);
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));
703 gst_memory_new_wrapped (0, cropped, dsize, 0, dsize, cropped,
g_free);
710 gst_buffer_copy_into (
result, raw, GST_BUFFER_COPY_METADATA, 0, -1);
714 gst_memory_unmap (mem, &map);
715 gst_memory_unref (mem);
726 GstCollectData * data_raw, GstCollectData * data_info)
729 GstBuffer *buf_raw, *buf_info, *
result;
732 gboolean drop_raw, drop_info;
734 g_return_val_if_fail (data_raw && data_info, GST_FLOW_ERROR);
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);
741 if (!buf_raw || !buf_info) {
755 if (self->lateness >= 0) {
756 GstClockTime ts_raw, ts_info, lateness;
758 ts_raw = GST_BUFFER_TIMESTAMP (buf_raw);
759 ts_info = GST_BUFFER_TIMESTAMP (buf_info);
760 lateness =
self->lateness * GST_MSECOND;
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));
771 if (ts_raw > ts_info)
780 GST_WARNING_OBJECT (
self,
781 "Incoming buffer has invalid timestamp, continue cropping data.");
786 ret = GST_FLOW_ERROR;
791 ret = gst_pad_push (self->srcpad,
result);
795 gst_buffer_unref (buf_raw);
797 gst_buffer_unref (buf_info);
801 gst_buffer_unref (gst_collect_pads_pop (self->collect, data_raw));
803 gst_buffer_unref (gst_collect_pads_pop (self->collect, data_info));
815 GstCollectData *data_raw, *data_info;
820 data_raw = data_info = NULL;
823 if (ret != GST_FLOW_OK)
826 for (walk = pads->data; walk; walk = g_slist_next (walk)) {
827 GstCollectData *
data;
829 data = (GstCollectData *) walk->data;
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 ());
836 if (
data->pad == self->sinkpad_raw) {
838 }
else if (
data->pad == self->sinkpad_info) {