73 #define GST_CAT_DEFAULT gst_tensor_demux_debug
78 #define CAPS_STRING_SINK GST_TENSORS_CAP_MAKE ("{ static, flexible }")
83 #define CAPS_STRING_SRC GST_TENSOR_CAP_DEFAULT ";" GST_TENSORS_CAP_MAKE ("{ static, flexible }")
96 static GstStaticPadTemplate
src_templ = GST_STATIC_PAD_TEMPLATE (
"src_%u",
102 static GstStaticPadTemplate
sink_templ = GST_STATIC_PAD_TEMPLATE (
"sink",
113 GstStateChange transition);
115 const GValue * value, GParamSpec * pspec);
117 GValue * value, GParamSpec * pspec);
119 #define gst_tensor_demux_parent_class parent_class
129 GObjectClass *gobject_class;
130 GstElementClass *gstelement_class;
132 GST_DEBUG_CATEGORY_INIT (gst_tensor_demux_debug,
"tensor_demux", 0,
133 "Element to demux tensors to tensor stream");
135 gobject_class = (GObjectClass *) klass;
136 gstelement_class = (GstElementClass *) klass;
138 parent_class = g_type_class_peek_parent (klass);
144 g_object_class_install_property (gobject_class,
PROP_SILENT,
145 g_param_spec_boolean (
"silent",
"Silent",
"Produce verbose output ?",
146 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
149 g_param_spec_string (
"tensorpick",
"TensorPick",
150 "Choose nth tensor among tensors ?",
"",
151 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
153 gstelement_class->change_state =
156 gst_element_class_add_pad_template (gstelement_class,
158 gst_element_class_add_pad_template (gstelement_class,
159 gst_static_pad_template_get (&
src_templ));
161 gst_element_class_set_details_simple (gstelement_class,
164 "Demux tensors stream to other/tensor stream",
165 "Jijoong Moon <jijoong.moon@samsung.com>");
178 gst_pad_new_from_static_template (&
sink_templ,
"sink");
179 gst_element_add_pad (GST_ELEMENT_CAST (tensor_demux), tensor_demux->
sinkpad);
180 gst_pad_set_chain_function (tensor_demux->
sinkpad,
182 gst_pad_set_event_function (tensor_demux->
sinkpad,
201 while (tensor_demux->
srcpads != NULL) {
203 gst_element_remove_pad (GST_ELEMENT (tensor_demux), tensor_pad->
pad);
206 g_slist_delete_link (tensor_demux->
srcpads, tensor_demux->
srcpads);
225 G_OBJECT_CLASS (parent_class)->dispose (
object);
237 GstStructure *structure;
242 structure = gst_caps_get_structure (caps, 0);
257 switch (GST_EVENT_TYPE (event)) {
261 gst_event_parse_caps (event, &caps);
267 GST_ELEMENT_ERROR (tensor_demux, STREAM, WRONG_TYPE,
268 (
"This stream contains no valid stremas."),
269 (
"Got EOS before adding any pads"));
270 gst_event_unref (event);
278 return gst_pad_event_default (pad, parent, event);
296 gchar *selected_tensor;
302 selected_tensor = (gchar *) g_list_nth_data (tensor_demux->
tensorpick, nth);
303 strv = g_strsplit_set (selected_tensor,
":+", -1);
304 num = g_strv_length (strv);
306 for (i = 0; i < num; i++) {
307 idx = (guint) g_ascii_strtoll (strv[i], NULL, 10);
350 gboolean * created,
const guint nth,
const guint total)
352 GstElement *element = GST_ELEMENT_CAST (tensor_demux);
353 g_autofree gchar *element_name = gst_element_get_name (element);
360 GstCaps *caps = NULL;
366 if (nth == pad->
nth) {
377 GST_DEBUG_OBJECT (tensor_demux,
"creating pad: %d(%dth)",
380 name = g_strdup_printf (
"src_%u", tensor_demux->
num_srcpads);
381 pad = gst_pad_new_from_static_template (&
src_templ, name);
382 stream_id = gst_pad_create_stream_id_printf (pad, element,
383 "%s-nnsdemux-%s-%08x", element_name, name, g_random_int ());
386 tensorpad->
pad = pad;
387 tensorpad->
nth = nth;
389 tensorpad->
last_ts = GST_CLOCK_TIME_NONE;
391 tensor_demux->
srcpads = g_slist_append (tensor_demux->
srcpads, tensorpad);
394 gst_pad_use_fixed_caps (pad);
395 gst_pad_set_active (pad,
TRUE);
396 gst_element_add_pad (GST_ELEMENT_CAST (tensor_demux), pad);
400 gst_pad_get_sticky_event (tensor_demux->
sinkpad, GST_EVENT_STREAM_START,
404 gst_event_parse_group_id (event, &tensor_demux->
group_id);
405 gst_event_unref (event);
408 tensor_demux->
group_id = gst_util_group_id_next ();
412 event = gst_event_new_stream_start (stream_id);
414 gst_event_set_group_id (event, tensor_demux->
group_id);
416 gst_pad_store_sticky_event (pad, event);
418 gst_event_unref (event);
424 gst_pad_set_caps (pad, caps);
425 gst_caps_unref (caps);
427 GST_WARNING_OBJECT (tensor_demux,
"Unable to set pad caps");
435 GST_DEBUG_OBJECT (tensor_demux,
"TensorPick is set! : %dth tensor\n", nth);
437 gst_element_no_more_pads (GST_ELEMENT_CAST (tensor_demux));
459 if (ret != GST_FLOW_NOT_LINKED)
462 for (walk = tensor_demux->
srcpads; walk; walk = g_slist_next (walk)) {
465 if (ret != GST_FLOW_NOT_LINKED)
478 guint num_tensors, num_srcs, i, idx;
479 GstFlowReturn res = GST_FLOW_OK;
498 GST_DEBUG_OBJECT (tensor_demux,
" Number of Tensors: %d", num_tensors);
500 num_srcs = num_tensors;
502 num_srcs = g_list_length (tensor_demux->
tensorpick);
506 for (i = 0; i < num_srcs; i++) {
515 outbuf = gst_buffer_new ();
519 gchar **strv = g_strsplit_set ((gchar *) list->data,
":+", -1);
521 num = g_strv_length (strv);
522 for (j = 0; j < num; j++) {
523 idx = (guint) g_ascii_strtoll (strv[j], NULL, 10);
529 gst_buffer_unref (outbuf);
530 res = GST_FLOW_ERROR;
541 gst_buffer_unref (outbuf);
542 res = GST_FLOW_ERROR;
547 ts = GST_BUFFER_TIMESTAMP (buf);
551 gst_segment_init (&segment, GST_FORMAT_TIME);
552 gst_pad_push_event (srcpad->
pad, gst_event_new_segment (&segment));
555 outbuf = gst_buffer_make_writable (outbuf);
558 gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
560 if (srcpad->
last_ts == GST_CLOCK_TIME_NONE || srcpad->
last_ts != ts) {
563 GST_DEBUG_OBJECT (tensor_demux,
"invalid timestamp %" GST_TIME_FORMAT,
567 GST_DEBUG_OBJECT (tensor_demux,
568 "pushing buffer with timestamp %" GST_TIME_FORMAT,
569 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
570 res = gst_pad_push (srcpad->
pad, outbuf);
573 if (res != GST_FLOW_OK)
578 gst_buffer_unref (buf);
585 static GstStateChangeReturn
589 GstStateChangeReturn ret;
591 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
592 if (ret == GST_STATE_CHANGE_FAILURE)
594 switch (transition) {
595 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
597 case GST_STATE_CHANGE_PAUSED_TO_READY:
602 case GST_STATE_CHANGE_READY_TO_NULL:
616 const GValue * value, GParamSpec * pspec)
621 filter->
silent = g_value_get_boolean (value);
626 const gchar *param = g_value_get_string (value);
627 gchar **strv = g_strsplit_set (param,
",.;/", -1);
628 guint num = g_strv_length (strv);
635 for (i = 0; i < num; i++) {
636 gchar *tmp = g_strdup (strv[i]);
643 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
653 GValue * value, GParamSpec * pspec)
658 g_value_set_boolean (value, filter->
silent);
664 GPtrArray *arr = g_ptr_array_new ();
667 for (list = filter->
tensorpick; list != NULL; list = list->next) {
668 g_ptr_array_add (arr, g_strdup_printf (
"%s", (gchar *) list->data));
670 g_ptr_array_add (arr, NULL);
671 strings = (gchar **) g_ptr_array_free (arr,
FALSE);
672 p = g_strjoinv (
",", strings);
673 g_strfreev (strings);
674 g_value_take_string (value, p);
678 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);