60 #define GST_CAT_DEFAULT gst_tensor_split_debug
73 #define CAPS_STRING GST_TENSOR_CAP_DEFAULT ";" GST_TENSORS_CAP_WITH_NUM ("1")
79 static GstStaticPadTemplate
src_templ = GST_STATIC_PAD_TEMPLATE (
"src_%u",
84 static GstStaticPadTemplate
sink_templ = GST_STATIC_PAD_TEMPLATE (
"sink",
94 GstStateChange transition);
96 const GValue * value, GParamSpec * pspec);
98 GValue * value, GParamSpec * pspec);
101 #define gst_tensor_split_parent_class parent_class
111 GObjectClass *gobject_class;
112 GstElementClass *gstelement_class;
114 GST_DEBUG_CATEGORY_INIT (gst_tensor_split_debug,
"tensor_split", 0,
115 "Element to split tensors stream to tensor stream");
117 gobject_class = (GObjectClass *) klass;
118 gstelement_class = (GstElementClass *) klass;
120 parent_class = g_type_class_peek_parent (klass);
126 g_object_class_install_property (gobject_class,
PROP_SILENT,
127 g_param_spec_boolean (
"silent",
"Silent",
128 "Do not produce verbose output ?",
TRUE, G_PARAM_READWRITE));
131 g_param_spec_string (
"tensorpick",
"TensorPick",
132 "Choose nth tensor among tensors ?",
"", G_PARAM_READWRITE));
135 g_param_spec_string (
"tensorseg",
"TensorSeg",
136 "How to split tensor ?",
"", G_PARAM_READWRITE));
138 gstelement_class->change_state =
141 gst_element_class_add_pad_template (gstelement_class,
143 gst_element_class_add_pad_template (gstelement_class,
144 gst_static_pad_template_get (&
src_templ));
146 gst_element_class_set_details_simple (gstelement_class,
149 "Split tensor stream to other/tensor stream",
150 "Jijoong Moon <jijoong.moon@samsung.com>");
163 gst_element_add_pad (GST_ELEMENT_CAST (split), split->
sinkpad);
164 gst_pad_set_chain_function (split->
sinkpad,
166 gst_pad_set_event_function (split->
sinkpad,
186 while (split->
srcpads != NULL) {
188 gst_element_remove_pad (GST_ELEMENT (split), tensor_pad->
pad);
210 G_OBJECT_CLASS (parent_class)->finalize (
object);
224 st = gst_caps_get_structure (caps, 0);
239 switch (GST_EVENT_TYPE (event)) {
243 gst_event_parse_caps (event, &caps);
245 GST_ELEMENT_ERROR (split, STREAM, WRONG_TYPE,
246 (
"This stream contains no valid type."), NULL);
252 GST_ELEMENT_ERROR (split, STREAM, WRONG_TYPE,
253 (
"This stream contains no valid stremas."),
254 (
"Got EOS before adding any pads"));
255 gst_event_unref (event);
263 return gst_pad_event_default (pad, parent, event);
277 gboolean * created, guint nth)
279 GstElement *element = GST_ELEMENT_CAST (split);
280 g_autofree gchar *element_name = gst_element_get_name (element);
296 if (nth == pad->
nth) {
302 walk = g_slist_next (walk);
307 GST_DEBUG_OBJECT (split,
"creating pad: %d(%dth)", split->
num_srcpads, nth);
309 name = g_strdup_printf (
"src_%u", split->
num_srcpads);
310 pad = gst_pad_new_from_static_template (&
src_templ, name);
311 stream_id = gst_pad_create_stream_id_printf (pad, element,
312 "%s-nnssplit-%s-%08x", element_name, name, g_random_int ());
315 tensorpad->
pad = pad;
316 tensorpad->
nth = nth;
318 tensorpad->
last_ts = GST_CLOCK_TIME_NONE;
325 gst_pad_use_fixed_caps (pad);
326 gst_pad_set_active (pad,
TRUE);
330 gst_pad_get_sticky_event (split->
sinkpad, GST_EVENT_STREAM_START, 0);
333 gst_event_unref (event);
336 split->
group_id = gst_util_group_id_next ();
340 event = gst_event_new_stream_start (stream_id);
342 gst_event_set_group_id (event, split->
group_id);
344 gst_pad_store_sticky_event (pad, event);
346 gst_event_unref (event);
360 gst_pad_set_caps (pad, caps);
361 gst_element_add_pad (GST_ELEMENT_CAST (split), pad);
363 gst_caps_unref (caps);
370 GST_DEBUG_OBJECT (split,
"TensorPick is set! : %dth tensor\n", nth);
372 gst_element_no_more_pads (GST_ELEMENT_CAST (split));
394 if (ret != GST_FLOW_NOT_LINKED)
397 for (walk = split->
srcpads; walk; walk = g_slist_next (walk)) {
400 if (ret != GST_FLOW_NOT_LINKED)
422 GstMapInfo src_info, dest_info;
428 mem = gst_allocator_alloc (NULL, size, NULL);
429 if (!gst_memory_map (mem, &dest_info, GST_MAP_WRITE)) {
430 ml_logf (
"Cannot map memory for destination buffer.\n");
431 gst_memory_unref (mem);
434 if (!gst_buffer_map (buffer, &src_info, GST_MAP_READ)) {
435 ml_logf (
"Cannot map src-memory to gst buffer at tensor-split.\n");
436 gst_memory_unmap (mem, &dest_info);
437 gst_memory_unref (mem);
442 for (i = 0; i < nth; i++) {
448 nns_memcpy (dest_info.data, src_info.data + offset, size);
449 gst_buffer_unmap (buffer, &src_info);
450 gst_memory_unmap (mem, &dest_info);
462 guint num_tensors, i;
463 GstFlowReturn res = GST_FLOW_OK;
469 GST_DEBUG_OBJECT (split,
" Number of Tensors: %d", num_tensors);
472 GST_ERROR_OBJECT (split,
"No rule to split incoming buffers.");
473 return GST_FLOW_ERROR;
476 for (i = 0; i < num_tensors; i++) {
484 gboolean found =
FALSE;
486 for (list = split->
tensorpick; list != NULL; list = list->next) {
487 if (i == GPOINTER_TO_UINT (list->data)) {
498 outbuf = gst_buffer_new ();
500 gst_buffer_append_memory (outbuf, mem);
501 ts = GST_BUFFER_TIMESTAMP (buf);
505 gst_segment_init (&segment, GST_FORMAT_TIME);
506 gst_pad_push_event (srcpad->
pad, gst_event_new_segment (&segment));
509 outbuf = gst_buffer_make_writable (outbuf);
512 gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
514 if (srcpad->
last_ts == GST_CLOCK_TIME_NONE || srcpad->
last_ts != ts) {
517 GST_DEBUG_OBJECT (split,
"invalid timestamp %" GST_TIME_FORMAT,
521 GST_DEBUG_OBJECT (split,
"pushing buffer with timestamp %" GST_TIME_FORMAT,
522 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
523 res = gst_pad_push (srcpad->
pad, outbuf);
525 if (res != GST_FLOW_OK)
529 gst_buffer_unref (buf);
536 static GstStateChangeReturn
540 GstStateChangeReturn ret;
544 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
545 if (ret == GST_STATE_CHANGE_FAILURE)
548 switch (transition) {
549 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
551 case GST_STATE_CHANGE_PAUSED_TO_READY:
556 case GST_STATE_CHANGE_READY_TO_NULL:
579 const GValue * value, GParamSpec * pspec)
587 split->
silent = g_value_get_boolean (value);
593 const gchar *param = g_value_get_string (value);
594 gchar **strv = g_strsplit_set (param,
",.;/", -1);
595 gint num = g_strv_length (strv);
596 for (i = 0; i < num; i++) {
597 val = g_ascii_strtoll (strv[i], NULL, 10);
599 g_list_append (split->
tensorpick, GINT_TO_POINTER (val));
607 const gchar *param = g_value_get_string (value);
608 gchar **strv = g_strsplit_set (param,
",.;/", -1);
612 if (NULL == tensorseg) {
616 g_array_set_clear_func (split->
tensorseg,
621 g_array_append_val (split->
tensorseg, d);
629 p = g_strsplit_set (strv[i],
":", -1);
630 num = g_strv_length (p);
632 d = g_array_index (tensorseg,
tensor_dim *, i);
634 for (k = 0; k < num; k++) {
635 (*d)[k] = g_ascii_strtod (p[k], NULL);
644 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
654 GValue * value, GParamSpec * pspec)
662 g_value_set_boolean (value, split->
silent);
668 GPtrArray *arr = g_ptr_array_new ();
671 for (list = split->
tensorpick; list != NULL; list = list->next) {
672 g_ptr_array_add (arr, g_strdup_printf (
"%i",
673 GPOINTER_TO_INT (list->data)));
675 g_ptr_array_add (arr, NULL);
676 strings = (gchar **) g_ptr_array_free (arr,
FALSE);
677 p = g_strjoinv (
",", strings);
678 g_strfreev (strings);
679 g_value_take_string (value, p);
690 for (i = 0; i < split->
tensorseg->len; i++) {
691 GPtrArray *arr = g_ptr_array_new ();
697 g_ptr_array_add (arr, g_strdup_printf (
"%i", (*dim)[j]));
699 g_ptr_array_add (arr, NULL);
700 strings = (gchar **) g_ptr_array_free (arr,
FALSE);
701 p = g_strjoinv (
":", strings);
702 g_strfreev (strings);
708 gchar *oldstrv = strv;
710 strv = g_strjoin (
",", strv, p, NULL);
718 g_value_take_string (value, strv ? strv : g_strdup (
""));
725 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);