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);
223 switch (GST_EVENT_TYPE (event)) {
227 gst_event_parse_caps (event, &caps);
229 GST_ELEMENT_ERROR (split, STREAM, WRONG_TYPE,
230 (
"This stream contains no valid type."), NULL);
236 GST_ELEMENT_ERROR (split, STREAM, WRONG_TYPE,
237 (
"This stream contains no valid stremas."),
238 (
"Got EOS before adding any pads"));
239 gst_event_unref (event);
247 return gst_pad_event_default (pad, parent, event);
261 gboolean * created, guint nth)
263 GstElement *element = GST_ELEMENT_CAST (split);
264 g_autofree gchar *element_name = gst_element_get_name (element);
280 if (nth == pad->
nth) {
286 walk = g_slist_next (walk);
291 GST_DEBUG_OBJECT (split,
"creating pad: %d(%dth)", split->
num_srcpads, nth);
293 name = g_strdup_printf (
"src_%u", split->
num_srcpads);
294 pad = gst_pad_new_from_static_template (&
src_templ, name);
295 stream_id = gst_pad_create_stream_id_printf (pad, element,
296 "%s-nnssplit-%s-%08x", element_name, name, g_random_int ());
299 tensorpad->
pad = pad;
300 tensorpad->
nth = nth;
302 tensorpad->
last_ts = GST_CLOCK_TIME_NONE;
309 gst_pad_use_fixed_caps (pad);
310 gst_pad_set_active (pad,
TRUE);
314 gst_pad_get_sticky_event (split->
sinkpad, GST_EVENT_STREAM_START, 0);
317 gst_event_unref (event);
320 split->
group_id = gst_util_group_id_next ();
324 event = gst_event_new_stream_start (stream_id);
326 gst_event_set_group_id (event, split->
group_id);
328 gst_pad_store_sticky_event (pad, event);
330 gst_event_unref (event);
344 gst_pad_set_caps (pad, caps);
345 gst_element_add_pad (GST_ELEMENT_CAST (split), pad);
347 gst_caps_unref (caps);
354 GST_DEBUG_OBJECT (split,
"TensorPick is set! : %dth tensor\n", nth);
356 gst_element_no_more_pads (GST_ELEMENT_CAST (split));
378 if (ret != GST_FLOW_NOT_LINKED)
381 for (walk = split->
srcpads; walk; walk = g_slist_next (walk)) {
384 if (ret != GST_FLOW_NOT_LINKED)
406 GstMapInfo src_info, dest_info;
412 mem = gst_allocator_alloc (NULL, size, NULL);
413 if (!gst_memory_map (mem, &dest_info, GST_MAP_WRITE)) {
414 ml_logf (
"Cannot map memory for destination buffer.\n");
415 gst_memory_unref (mem);
418 if (!gst_buffer_map (buffer, &src_info, GST_MAP_READ)) {
419 ml_logf (
"Cannot map src-memory to gst buffer at tensor-split.\n");
420 gst_memory_unmap (mem, &dest_info);
421 gst_memory_unref (mem);
426 for (i = 0; i < nth; i++) {
432 nns_memcpy (dest_info.data, src_info.data + offset, size);
433 gst_buffer_unmap (buffer, &src_info);
434 gst_memory_unmap (mem, &dest_info);
446 guint num_tensors, i;
447 GstFlowReturn res = GST_FLOW_OK;
453 GST_DEBUG_OBJECT (split,
" Number of Tensors: %d", num_tensors);
456 GST_ERROR_OBJECT (split,
"No rule to split incoming buffers.");
457 return GST_FLOW_ERROR;
460 for (i = 0; i < num_tensors; i++) {
468 gboolean found =
FALSE;
470 for (list = split->
tensorpick; list != NULL; list = list->next) {
471 if (i == GPOINTER_TO_UINT (list->data)) {
482 outbuf = gst_buffer_new ();
484 gst_buffer_append_memory (outbuf, mem);
485 ts = GST_BUFFER_TIMESTAMP (buf);
489 gst_segment_init (&segment, GST_FORMAT_TIME);
490 gst_pad_push_event (srcpad->
pad, gst_event_new_segment (&segment));
493 outbuf = gst_buffer_make_writable (outbuf);
496 gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
498 if (srcpad->
last_ts == GST_CLOCK_TIME_NONE || srcpad->
last_ts != ts) {
501 GST_DEBUG_OBJECT (split,
"invalid timestamp %" GST_TIME_FORMAT,
505 GST_DEBUG_OBJECT (split,
"pushing buffer with timestamp %" GST_TIME_FORMAT,
506 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
507 res = gst_pad_push (srcpad->
pad, outbuf);
509 if (res != GST_FLOW_OK)
513 gst_buffer_unref (buf);
520 static GstStateChangeReturn
524 GstStateChangeReturn ret;
528 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
529 if (ret == GST_STATE_CHANGE_FAILURE)
532 switch (transition) {
533 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
535 case GST_STATE_CHANGE_PAUSED_TO_READY:
540 case GST_STATE_CHANGE_READY_TO_NULL:
563 const GValue * value, GParamSpec * pspec)
571 split->
silent = g_value_get_boolean (value);
577 const gchar *param = g_value_get_string (value);
578 gchar **strv = g_strsplit_set (param,
",.;/", -1);
579 gint num = g_strv_length (strv);
580 for (i = 0; i < num; i++) {
581 val = g_ascii_strtoll (strv[i], NULL, 10);
583 g_list_append (split->
tensorpick, GINT_TO_POINTER (val));
591 const gchar *param = g_value_get_string (value);
592 gchar **strv = g_strsplit_set (param,
",.;/", -1);
596 if (NULL == tensorseg) {
600 g_array_set_clear_func (split->
tensorseg,
605 g_array_append_val (split->
tensorseg, d);
613 p = g_strsplit_set (strv[i],
":", -1);
614 num = g_strv_length (p);
616 d = g_array_index (tensorseg,
tensor_dim *, i);
618 for (k = 0; k < num; k++) {
619 (*d)[k] = g_ascii_strtod (p[k], NULL);
628 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
638 GValue * value, GParamSpec * pspec)
646 g_value_set_boolean (value, split->
silent);
652 GPtrArray *arr = g_ptr_array_new ();
655 for (list = split->
tensorpick; list != NULL; list = list->next) {
656 g_ptr_array_add (arr, g_strdup_printf (
"%i",
657 GPOINTER_TO_INT (list->data)));
659 g_ptr_array_add (arr, NULL);
660 strings = (gchar **) g_ptr_array_free (arr,
FALSE);
661 p = g_strjoinv (
",", strings);
662 g_strfreev (strings);
663 g_value_take_string (value, p);
674 for (i = 0; i < split->
tensorseg->len; i++) {
675 GPtrArray *arr = g_ptr_array_new ();
681 g_ptr_array_add (arr, g_strdup_printf (
"%i", (*dim)[j]));
683 g_ptr_array_add (arr, NULL);
684 strings = (gchar **) g_ptr_array_free (arr,
FALSE);
685 p = g_strjoinv (
":", strings);
686 g_strfreev (strings);
692 gchar *oldstrv = strv;
694 strv = g_strjoin (
",", strv, p, NULL);
702 g_value_take_string (value, strv ? strv : g_strdup (
""));
709 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);