69 #define GST_CAT_DEFAULT gst_tensor_mux_debug
75 #define DBG (!tensor_mux->silent)
89 #define CAPS_STRING_SINK GST_TENSOR_CAP_DEFAULT ";" GST_TENSORS_CAP_MAKE ("{ static, flexible }")
94 #define CAPS_STRING_SRC GST_TENSORS_CAP_MAKE ("{ static, flexible }")
100 static GstStaticPadTemplate
src_templ = GST_STATIC_PAD_TEMPLATE (
"src",
106 static GstStaticPadTemplate
sink_templ = GST_STATIC_PAD_TEMPLATE (
"sink_%u",
115 GstPadTemplate * templ,
const gchar * name,
const GstCaps * caps);
117 GstStateChange transition);
123 GstCollectData *
data, GstBuffer * buffer, GstBuffer ** out,
127 const GValue * value, GParamSpec * pspec);
129 GValue * value, GParamSpec * pspec);
132 #define gst_tensor_mux_parent_class parent_class
141 GObjectClass *gobject_class;
142 GstElementClass *gstelement_class;
144 GST_DEBUG_CATEGORY_INIT (gst_tensor_mux_debug,
"tensor_mux", 0,
145 "Element to merge tensor stream to tensors stream");
147 gobject_class = (GObjectClass *) klass;
148 gstelement_class = (GstElementClass *) klass;
150 parent_class = g_type_class_peek_parent (klass);
156 g_object_class_install_property (gobject_class,
PROP_SILENT,
157 g_param_spec_boolean (
"silent",
"Silent",
"Produce verbose output ?",
158 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
161 g_param_spec_string (
"sync-mode",
"Sync Mode",
162 "Time synchronization mode?",
"", G_PARAM_READWRITE));
165 g_param_spec_string (
"sync-option",
"Sync Option",
166 "Option for the time synchronization mode ?",
"", G_PARAM_READWRITE));
168 gstelement_class->request_new_pad =
170 gstelement_class->change_state =
173 gst_element_class_add_pad_template (gstelement_class,
175 gst_element_class_add_pad_template (gstelement_class,
176 gst_static_pad_template_get (&
src_templ));
178 gst_element_class_set_details_simple (gstelement_class,
181 "Merge multiple tensor stream to tensors stream",
182 "Jijoong Moon <jijoong.moon@samsung.com>");
195 GstElementClass *klass = GST_ELEMENT_GET_CLASS (tensor_mux);
198 gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
202 gst_element_add_pad (GST_ELEMENT (tensor_mux), tensor_mux->
srcpad);
204 tensor_mux->
collect = gst_collect_pads_new ();
205 gst_collect_pads_set_event_function (tensor_mux->
collect,
206 (GstCollectPadsEventFunction)
208 gst_collect_pads_set_function (tensor_mux->
collect,
211 gst_collect_pads_set_clip_function (tensor_mux->
collect,
235 gst_object_unref (tensor_mux->
collect);
246 G_OBJECT_CLASS (parent_class)->finalize (
object);
254 const gchar * req_name,
const GstCaps * caps)
263 g_return_val_if_fail (templ != NULL, NULL);
267 walk = tensor_mux->
collect->data;
269 name = g_strdup_printf (
"sink_%u", g_slist_length (walk));
270 newpad = gst_pad_new_from_template (templ, name);
275 gboolean locked, waiting;
277 locked = waiting =
TRUE;
280 locked = waiting =
FALSE;
284 gst_collect_pads_add_pad (tensor_mux->
collect, newpad,
288 gst_collect_pads_set_waiting (tensor_mux->
collect,
289 (GstCollectData *) tensormuxpad, waiting);
291 gst_pad_set_element_private (newpad, tensormuxpad);
292 gst_element_add_pad (element, newpad);
294 GST_WARNING_OBJECT (tensor_mux,
"failed to create request pad");
305 g_return_val_if_fail (event != NULL,
FALSE);
307 switch (GST_EVENT_TYPE (event)) {
309 gst_event_unref (event);
315 return gst_pad_event_default (pad, parent, event);
325 GstCollectPads *pads = tensor_mux->
collect;
326 GSList *walk = pads->data;
329 gst_collect_pads_set_waiting (pads, walk->data, waiting);
330 walk = g_slist_next (walk);
342 g_return_val_if_fail (event != NULL,
FALSE);
344 switch (GST_EVENT_TYPE (event)) {
345 case GST_EVENT_FLUSH_STOP:
357 return gst_collect_pads_event_default (pads,
data, event,
FALSE);
369 GstBuffer * tensors_buf, gboolean * is_eos)
380 silent_debug (tensor_mux,
"Current Time : %" GST_TIME_FORMAT,
402 if (gst_pad_set_caps (tensor_mux->
srcpad, caps)) {
406 gst_caps_unref (caps);
411 GST_WARNING_OBJECT (tensor_mux,
"failed to set caps");
412 GST_ELEMENT_ERROR (tensor_mux, CORE, NEGOTIATION, (NULL), (NULL));
423 GstClockTime pts, GstClockTime dts)
427 GstClockTime time = 0;
429 if (GST_CLOCK_TIME_IS_VALID (dts)) {
431 }
else if (GST_CLOCK_TIME_IS_VALID (pts)) {
435 gst_segment_init (&segment, GST_FORMAT_TIME);
436 segment.start = time;
437 gst_pad_push_event (tensor_mux->
srcpad, gst_event_new_segment (&segment));
449 GstMemory *mem, *new_mem;
460 buffer = gst_buffer_new ();
469 gst_memory_unref (mem);
474 gst_buffer_copy_into (buffer, buf, GST_BUFFER_COPY_METADATA, 0, -1);
475 gst_buffer_unref (buf);
488 GstFlowReturn ret = GST_FLOW_OK;
489 GstBuffer *tensors_buf;
490 gboolean isEOS =
FALSE;
491 gboolean buf_collected =
FALSE;
493 GST_DEBUG_OBJECT (tensor_mux,
" all pads are collected ");
500 GstCollectData *
data = (GstCollectData *) pads->data->data;
501 g_autofree gchar *sink_stream_id = gst_pad_get_stream_id (
data->pad);
502 g_autofree gchar *element_name = gst_element_get_name (tensor_mux);
503 g_autofree gchar *pad_name = gst_pad_get_name (tensor_mux->
srcpad);
504 g_autofree gchar *stream_id = g_strdup_printf (
"%s-%s-nnsmux-%s-%08x",
505 GST_STR_NULL (sink_stream_id), element_name, pad_name, g_random_int ());
507 gst_pad_push_event (tensor_mux->
srcpad, gst_event_new_stream_start (stream_id));
511 if ((tensors_buf = gst_buffer_new ()) == NULL) {
512 ml_logf (
"gst_buffer_new() returns NULL. Out of memory?\n");
513 return GST_FLOW_ERROR;
521 if (!buf_collected) {
523 gst_pad_push_event (tensor_mux->
srcpad, gst_event_new_eos ());
527 gst_buffer_unref (tensors_buf);
532 gst_buffer_unref (tensors_buf);
533 return GST_FLOW_NOT_NEGOTIATED;
537 GST_BUFFER_DTS (tensors_buf));
543 ret = gst_pad_push (tensor_mux->
srcpad, tensors_buf);
546 if (ret != GST_FLOW_OK) {
547 GST_WARNING_OBJECT (tensor_mux,
"pushed outbuf, result = %s",
548 gst_flow_get_name (ret));
559 GstBuffer * buffer, GstBuffer ** out,
GstTensorMux * tensor_mux)
577 gst_collect_pads_start (tensor_mux->
collect);
583 static GstStateChangeReturn
587 GstStateChangeReturn ret;
589 switch (transition) {
590 case GST_STATE_CHANGE_READY_TO_PAUSED:
593 case GST_STATE_CHANGE_PAUSED_TO_READY:
594 gst_collect_pads_stop (tensor_mux->
collect);
600 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
601 if (ret == GST_STATE_CHANGE_FAILURE)
603 switch (transition) {
604 case GST_STATE_CHANGE_PAUSED_TO_READY:
618 const GValue * value, GParamSpec * pspec)
623 tensor_mux->
silent = g_value_get_boolean (value);
636 tensor_mux->
sync.
option = g_value_dup_string (value);
641 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
651 GValue * value, GParamSpec * pspec)
656 g_value_set_boolean (value, tensor_mux->
silent);
666 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);