From: jijoong.moon Date: Tue, 10 Jul 2018 00:35:09 +0000 (+0900) Subject: [TensorMux] Set Capability & using private date for sink pad X-Git-Tag: v0.0.1~69 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8a76aa3425dab110fb22063a173eded5b7fe9988;p=platform%2Fupstream%2Fnnstreamer.git [TensorMux] Set Capability & using private date for sink pad Added vmthods - gst_tesnor_mux_request_new_pad : set new sink pad & call setup - gst_tensor_mux_release_pad : release pad - gst_tensor_mux_setup_sinkpad : initialize pad - gst_tensor_mux_chain : actual calculation of buffers - gst_tensor_mux_setcaps : set capability - gst_tensor_mux_sink_event : event handling ( cap, segment, start ) - gst_tensor_mux_dispose : dispose tensor mux - gst_tensor_mux_change_state : state handler Signed-off-by: jijoong.moon --- diff --git a/gst/tensor_mux/gsttensormux.c b/gst/tensor_mux/gsttensormux.c index 1746157..2611147 100644 --- a/gst/tensor_mux/gsttensormux.c +++ b/gst/tensor_mux/gsttensormux.c @@ -63,21 +63,18 @@ #include "gsttensormux.h" #include -GST_DEBUG_CATEGORY_STATIC (gst_tensormux_debug); -#define GST_CAT_DEFAULT gst_tensormux_debug - -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; +GST_DEBUG_CATEGORY_STATIC (gst_tensor_mux_debug); +#define GST_CAT_DEFAULT gst_tensor_mux_debug enum { PROP_0, + PROP_TIMESTAMP_OFFSET, PROP_SILENT }; +#define DEFAULT_TIMESTAMP_OFFSET -1 + /** * @brief the capabilities of the inputs and outputs. * describe the real formats here. @@ -95,25 +92,27 @@ static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink_%u", ); #define gst_tensor_mux_parent_class parent_class -G_DEFINE_TYPE (GstTensorMux, gst_tensor_mux, GST_TYPE_ELEMENT); - -static gboolean -gst_tensor_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event); - -static void gst_tensor_mux_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_tensor_mux_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); static GstPad *gst_tensor_mux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps); static void gst_tensor_mux_release_pad (GstElement * element, GstPad * pad); - static GstFlowReturn -gst_tensor_mux_chain (GstPad * pad, GstObject * object, GstBuffer * buffer); - +gst_tensor_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer); static gboolean -gst_tensor_mux_pad_setcaps (GstPad * pad, GstObject * parent, GstCaps * caps); +gst_tensor_mux_setcaps (GstPad * pad, GstTensorMux * tensor_mux, + GstCaps * caps); +static gboolean gst_tensor_mux_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static GstStateChangeReturn gst_tensor_mux_change_state (GstElement * element, + GstStateChange transition); +static void gst_tensor_mux_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tensor_mux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_tensor_mux_dispose (GObject * object); + +G_DEFINE_TYPE (GstTensorMux, gst_tensor_mux, GST_TYPE_ELEMENT); + /** * @brief initialize the tensor_mux's class @@ -127,17 +126,31 @@ gst_tensor_mux_class_init (GstTensorMuxClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_templ)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_templ)); + gobject_class->get_property = gst_tensor_mux_get_property; gobject_class->set_property = gst_tensor_mux_set_property; - + gobject_class->dispose = gst_tensor_mux_dispose; + + g_object_class_install_property (gobject_class, + PROP_TIMESTAMP_OFFSET, g_param_spec_int ("timestamp-offset", + "Timestamp Offset", + "Offset to add to all outgoing timestamps (-1 = random)", -1, + G_MAXINT, DEFAULT_TIMESTAMP_OFFSET, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_SILENT, g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", FALSE, G_PARAM_READWRITE)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sink_templ)); - gstelement_class->request_new_pad = gst_tensor_mux_request_new_pad; - gstelement_class->release_pad = gst_tensor_mux_release_pad; + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_tensor_mux_request_new_pad); + gstelement_class->release_pad = + GST_DEBUG_FUNCPTR (gst_tensor_mux_release_pad); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_tensor_mux_change_state); gst_element_class_set_details_simple (gstelement_class, "tensormux", @@ -148,19 +161,76 @@ gst_tensor_mux_class_init (GstTensorMuxClass * klass) } /** + * @brief dispose tensor mux / tensor mux pad object + * @param object GstTensorMux* + */ +static void +gst_tensor_mux_dispose (GObject * object) +{ + GstTensorMux *tensor_mux = GST_TENSOR_MUX (object); + GList *item; + + g_clear_object (&tensor_mux->last_pad); + +restart: + for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { + GstPad *pad = GST_PAD (item->data); + if (GST_PAD_IS_SINK (pad)) { + gst_element_release_request_pad (GST_ELEMENT (object), pad); + goto restart; + } + } + + G_OBJECT_CLASS (gst_tensor_mux_parent_class)->dispose (object); +} + + +/** * @brief initialize the new element * instantiate pads and add them to element * set pad calback functions * initialize instance structure */ static void -gst_tensor_mux_init (GstTensorMux * mux) +gst_tensor_mux_init (GstTensorMux * tensor_mux) { - mux->srcpad = gst_pad_new_from_static_template (&src_templ, "src"); - gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad); - mux->num_tensors = 0; - mux->byte_count = 0; - mux->silent = FALSE; + GstElementClass *klass = GST_ELEMENT_GET_CLASS (tensor_mux); + tensor_mux->srcpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "src"), "src"); + gst_pad_use_fixed_caps (tensor_mux->srcpad); + gst_element_add_pad (GST_ELEMENT (tensor_mux), tensor_mux->srcpad); + + tensor_mux->num_tensors = 0; + tensor_mux->byte_count = 0; + tensor_mux->silent = FALSE; + tensor_mux->first = TRUE; + tensor_mux->rank = 0; + tensor_mux->dimensions = g_string_new (NULL); + tensor_mux->types = g_string_new (NULL); + tensor_mux->outbuffer = gst_buffer_new (); +} + +/** + * @brief Setup Sink Pad for tensor mux + * Initialize pad private data & set functions for pad + * @param tensor_mux GstTensorMux Pointer + * @param sinkpad Sink pad + */ +static void +gst_tensor_mux_setup_sinkpad (GstTensorMux * tensor_mux, GstPad * sinkpad) +{ + GstTensorMuxPadPrivate *padpriv = g_slice_new0 (GstTensorMuxPadPrivate); + padpriv->done = FALSE; + gst_pad_set_chain_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_tensor_mux_chain)); + gst_pad_set_event_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_tensor_mux_sink_event)); + + gst_pad_set_element_private (sinkpad, padpriv); + + gst_pad_set_active (sinkpad, TRUE); + gst_element_add_pad (GST_ELEMENT (tensor_mux), sinkpad); } @@ -169,17 +239,29 @@ gst_tensor_mux_init (GstTensorMux * mux) */ static GstPad * gst_tensor_mux_request_new_pad (GstElement * element, GstPadTemplate * templ, - const gchar * name, const GstCaps * caps) + const gchar * req_name, const GstCaps * caps) { - GstPad *pad; - pad = gst_pad_new_from_template (templ, name); + GstPad *newpad; + GstTensorMux *tensor_mux; - gst_pad_set_event_function (pad, - GST_DEBUG_FUNCPTR (gst_tensor_mux_sink_event)); - gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_tensor_mux_chain)); + g_return_val_if_fail (templ != NULL, NULL); + g_return_val_if_fail (GST_IS_TENSOR_MUX (element), NULL); - gst_element_add_pad (element, pad); - return pad; + tensor_mux = GST_TENSOR_MUX (element); + + if (templ->direction != GST_PAD_SINK) { + GST_WARNING_OBJECT (tensor_mux, "request pad that is not a SINK pad"); + return NULL; + } + + newpad = gst_pad_new_from_template (templ, req_name); + + if (newpad) + gst_tensor_mux_setup_sinkpad (tensor_mux, newpad); + else + GST_WARNING_OBJECT (tensor_mux, "failed to create request pad"); + + return newpad; } /** @@ -188,7 +270,225 @@ gst_tensor_mux_request_new_pad (GstElement * element, GstPadTemplate * templ, static void gst_tensor_mux_release_pad (GstElement * element, GstPad * pad) { - gst_element_remove_pad (element, pad); + GstTensorMuxPadPrivate *padpriv; + GstTensorMux *tensor_mux = GST_TENSOR_MUX_CAST (element); + + GST_DEBUG_OBJECT (tensor_mux, "releaseing pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + gst_pad_set_active (pad, FALSE); + + GST_OBJECT_LOCK (element); + padpriv = gst_pad_get_element_private (pad); + gst_pad_set_element_private (pad, NULL); + GST_OBJECT_UNLOCK (element); + gst_element_remove_pad (GST_ELEMENT_CAST (tensor_mux), pad); + if (padpriv) { + g_slice_free (GstTensorMuxPadPrivate, padpriv); + } +} + +/** + * @brief resend events for sticky events + */ +static gboolean +resend_events (GstPad * pad, GstEvent ** event, gpointer user_data) +{ + GstTensorMux *tensor_mux = user_data; + + if (GST_EVENT_TYPE (*event) == GST_EVENT_CAPS) { + GstCaps *caps; + + gst_event_parse_caps (*event, &caps); + gst_tensor_mux_setcaps (pad, tensor_mux, caps); + } else if (GST_EVENT_TYPE (*event) == GST_EVENT_SEGMENT) { + GstSegment new_segment; + gst_segment_init (&new_segment, GST_FORMAT_TIME); + gst_pad_push_event (tensor_mux->srcpad, + gst_event_new_segment (&new_segment)); + } else { + gst_pad_push_event (tensor_mux->srcpad, gst_event_ref (*event)); + } + + return TRUE; +} + +/** + * @brief chain function (gst element vmethod) + */ +static GstFlowReturn +gst_tensor_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstTensorMux *tensor_mux; + GstFlowReturn ret; + GstTensorMuxPadPrivate *padpriv; + gboolean changed = FALSE; + tensor_mux = GST_TENSOR_MUX (parent); + + GST_DEBUG_OBJECT (pad, "recevied %" GST_PTR_FORMAT, buffer); + + if (gst_pad_check_reconfigure (tensor_mux->srcpad)) { + GstCaps *current_caps = gst_pad_get_current_caps (pad); + if (!gst_tensor_mux_setcaps (pad, tensor_mux, current_caps)) { + gst_pad_mark_reconfigure (tensor_mux->srcpad); + if (GST_PAD_IS_FLUSHING (tensor_mux->srcpad)) + ret = GST_FLOW_FLUSHING; + else + ret = GST_FLOW_NOT_NEGOTIATED; + goto out; + } + gst_caps_unref (current_caps); + } + + GST_OBJECT_LOCK (tensor_mux); + padpriv = gst_pad_get_element_private (pad); + + if (!padpriv) { + GST_OBJECT_UNLOCK (tensor_mux); + gst_buffer_unref (buffer); + return GST_FLOW_NOT_LINKED; + } + + buffer = gst_buffer_make_writable (buffer); + + + /* @TODO tensors buffer & data with tensor */ + + if (pad != tensor_mux->last_pad) { + changed = TRUE; + g_clear_object (&tensor_mux->last_pad); + tensor_mux->last_pad = g_object_ref (pad); + } + + if (GST_BUFFER_DURATION_IS_VALID (buffer) && GST_BUFFER_PTS_IS_VALID (buffer)) + tensor_mux->last_stop = + GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer); + else + tensor_mux->last_stop = GST_CLOCK_TIME_NONE; + + GST_OBJECT_UNLOCK (tensor_mux); + + if (changed) + gst_pad_sticky_events_foreach (pad, resend_events, tensor_mux); + + gst_buffer_unref (buffer); + gst_buffer_ref (tensor_mux->outbuffer); + ret = gst_pad_push (tensor_mux->srcpad, tensor_mux->outbuffer); +out: + return ret; +} + + +/** + * @brief set caps (gst element vmethod) + */ +static gboolean +gst_tensor_mux_setcaps (GstPad * pad, GstTensorMux * tensor_mux, GstCaps * caps) +{ + GstStructure *structure; + gboolean ret = FALSE; + GstTensorMuxPadPrivate *padpriv; + GstCaps *peercaps, *src_caps; + gint dim; + const gchar *t; + + GST_DEBUG_OBJECT (tensor_mux, "setcaps for pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + padpriv = gst_pad_get_element_private (pad); + if (padpriv->done) + return TRUE; + if (!gst_caps_is_fixed (caps)) + return FALSE; + + peercaps = gst_pad_peer_query_caps (tensor_mux->srcpad, NULL); + if (peercaps) { + GstCaps *tcaps, *othercaps; + tcaps = gst_pad_get_pad_template_caps (pad); + othercaps = + gst_caps_intersect_full (peercaps, tcaps, GST_CAPS_INTERSECT_FIRST); + + if (gst_caps_get_size (othercaps) > 0) { + structure = gst_caps_get_structure (othercaps, 0); + GST_OBJECT_LOCK (tensor_mux); + tensor_mux->first = FALSE; + GST_OBJECT_UNLOCK (tensor_mux); + } + + gst_caps_unref (othercaps); + gst_caps_unref (peercaps); + gst_caps_unref (tcaps); + } + + + structure = gst_caps_get_structure (caps, 0); + if (!structure) + return FALSE; + + GST_OBJECT_LOCK (tensor_mux); + tensor_mux->num_tensors++; + gst_structure_get_int (structure, "rank", &tensor_mux->rank); + gst_structure_get_int (structure, "dim1", &dim); + if (tensor_mux->dimensions->len != 0) + tensor_mux->dimensions = g_string_append (tensor_mux->dimensions, ","); + tensor_mux->dimensions = + g_string_append (tensor_mux->dimensions, g_strdup_printf ("%d", dim)); + tensor_mux->dimensions = g_string_append (tensor_mux->dimensions, ":"); + gst_structure_get_int (structure, "dim2", &dim); + tensor_mux->dimensions = + g_string_append (tensor_mux->dimensions, g_strdup_printf ("%d", dim)); + tensor_mux->dimensions = g_string_append (tensor_mux->dimensions, ":"); + gst_structure_get_int (structure, "dim3", &dim); + tensor_mux->dimensions = + g_string_append (tensor_mux->dimensions, g_strdup_printf ("%d", dim)); + tensor_mux->dimensions = g_string_append (tensor_mux->dimensions, ":"); + gst_structure_get_int (structure, "dim4", &dim); + tensor_mux->dimensions = + g_string_append (tensor_mux->dimensions, g_strdup_printf ("%d", dim)); + + if (tensor_mux->types->len != 0) + tensor_mux->types = g_string_append (tensor_mux->types, ","); + t = gst_structure_get_string (structure, "type"); + tensor_mux->types = g_string_append (tensor_mux->types, t); + + + gst_structure_get_fraction (structure, "framerate", + &tensor_mux->framerate_numerator, &tensor_mux->framerate_denominator); + + padpriv = gst_pad_get_element_private (pad); + if (padpriv + && gst_structure_get_uint (structure, "timestamps-offset", + &padpriv->timestamp_offset)) { + padpriv->have_timestamp_offset = TRUE; + } + + padpriv->done = TRUE; + src_caps = gst_caps_new_simple ("other/tensors", + "rank", G_TYPE_INT, tensor_mux->rank, + "num_tensors", G_TYPE_INT, tensor_mux->num_tensors, + "types", G_TYPE_STRING, tensor_mux->types->str, + "framerate", GST_TYPE_FRACTION, tensor_mux->framerate_numerator, + tensor_mux->framerate_denominator, "dimensions", G_TYPE_STRING, + tensor_mux->dimensions->str, NULL); + + GST_OBJECT_UNLOCK (tensor_mux); + + if (tensor_mux->send_stream_start) { + gchar s_id[32]; + + g_snprintf (s_id, sizeof (s_id), "interleave-%08x", g_random_int ()); + gst_pad_push_event (tensor_mux->srcpad, gst_event_new_stream_start (s_id)); + + tensor_mux->send_stream_start = FALSE; + } + + GST_DEBUG_OBJECT (tensor_mux, + "setting caps %" GST_PTR_FORMAT " on src pad..", src_caps); + + ret = gst_pad_set_caps (tensor_mux->srcpad, src_caps); + gst_caps_unref (src_caps); + + return ret; } /** @@ -197,45 +497,109 @@ gst_tensor_mux_release_pad (GstElement * element, GstPad * pad) static gboolean gst_tensor_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { + GstTensorMux *mux = GST_TENSOR_MUX (parent); + gboolean is_pad; gboolean ret = TRUE; + GST_OBJECT_LOCK (mux); + is_pad = (pad == mux->last_pad); + GST_OBJECT_UNLOCK (mux); + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); - ret = gst_tensor_mux_pad_setcaps (pad, parent, caps); + GST_LOG_OBJECT (pad, "Received caps-event with caps: %" + GST_PTR_FORMAT, caps); + ret = gst_tensor_mux_setcaps (pad, mux, caps); + gst_event_unref (event); + return ret; + } + break; + case GST_EVENT_FLUSH_STOP: + { + GST_OBJECT_LOCK (mux); + mux->last_stop = GST_CLOCK_TIME_NONE; + GST_OBJECT_UNLOCK (mux); + break; + } + case GST_EVENT_SEGMENT: + { + GstTensorMuxPadPrivate *padpriv; + GST_OBJECT_LOCK (mux); + padpriv = gst_pad_get_element_private (pad); + + if (padpriv) { + gst_event_copy_segment (event, &padpriv->segment); + } + GST_OBJECT_UNLOCK (mux); + + if (is_pad) { + GstSegment new_segment; + gst_segment_init (&new_segment, GST_FORMAT_TIME); + gst_event_unref (event); + event = gst_event_new_segment (&new_segment); + } break; } default: break; } - if (!ret) - return FALSE; + if (is_pad) { + return gst_pad_push_event (mux->srcpad, event); + } else { + gst_event_unref (event); + return ret; + } +} - return ret; +/** + * @brief Ready --> Pasuse State Change + */ +static void +gst_tensor_mux_ready_to_paused (GstTensorMux * tensor_mux) +{ + GST_OBJECT_LOCK (tensor_mux); + g_clear_object (&tensor_mux->last_pad); + tensor_mux->send_stream_start = TRUE; + GST_OBJECT_UNLOCK (tensor_mux); } /** - * @brief set caps (gst element vmethod) + * @brief change state (gst element vmethod) */ -static gboolean -gst_tensor_mux_pad_setcaps (GstPad * pad, GstObject * parent, GstCaps * caps) +static GstStateChangeReturn +gst_tensor_mux_change_state (GstElement * element, GstStateChange transition) { - GstTensorMux *mux = GST_TENSOR_MUX (parent); - gboolean ret = TRUE; - GstStructure *s; + GstTensorMux *tensor_mux; + GstStateChangeReturn ret; + + tensor_mux = GST_TENSOR_MUX (element); - s = gst_caps_get_structure (caps, 0); - if (strcmp (gst_structure_get_name (s), "other/tensor") != 0) - ret = FALSE; + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_tensor_mux_ready_to_paused (tensor_mux); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (gst_tensor_mux_parent_class)->change_state (element, + transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + g_clear_object (&tensor_mux->last_pad); + break; + default: + break; + } - gst_object_unref (mux); return ret; } - /** * @brief Get property (gst element vmethod) */ @@ -274,50 +638,41 @@ gst_tensor_mux_get_property (GObject * object, guint prop_id, } } + +/** + * PACKAGE: this is usually set by autotools depending on some _INIT macro + * in configure.ac and then written into and defined in config.h, but we can + * just set it ourselves here in case someone doesn't use autotools to + * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined. + */ +#ifndef PACKAGE +#define PACKAGE "tensormux" +#endif + /** * @brief entry point to initialize the plug-in * initialize the plug-in itself * register the element factories and other features */ static gboolean -tensor_mux_init (GstPlugin * tensormux) +gst_tensor_mux_plugin_init (GstPlugin * tensormux) { /* debug category for fltering log messages - * * exchange the string 'Template tensor_mux' with your description */ - GST_DEBUG_CATEGORY_INIT (gst_tensormux_debug, "tensormux", 0, "Tensor Muxer"); + GST_DEBUG_CATEGORY_INIT (gst_tensor_mux_debug, "tensormux", 0, + "Tensor Muxer"); return gst_element_register (tensormux, "tensormux", GST_RANK_NONE, GST_TYPE_TENSOR_MUX); } /** - * PACKAGE: this is usually set by autotools depending on some _INIT macro - * in configure.ac and then written into and defined in config.h, but we can - * just set it ourselves here in case someone doesn't use autotools to - * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined. - */ -#ifndef PACKAGE -#define PACKAGE "tensormux" -#endif - -/* gstreamer looks for this structure to register tensor_converters - * - * exchange the string 'Template tensor_converter' with your tensor_converter description + * @brief gstreamer looks for this structure to register tensormux */ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, tensormux, "tensormux", - tensor_mux_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/"); - -/** - * @brief chain function (gst element vmethod) - */ -static GstFlowReturn -gst_tensor_mux_chain (GstPad * pad, GstObject * object, GstBuffer * buffer) -{ - gst_buffer_unref (buffer); - return GST_FLOW_OK; -} + gst_tensor_mux_plugin_init, VERSION, "LGPL", "GStreamer", + "http://gstreamer.net/"); diff --git a/gst/tensor_mux/gsttensormux.h b/gst/tensor_mux/gsttensormux.h index 9a6f139..f229b7a 100644 --- a/gst/tensor_mux/gsttensormux.h +++ b/gst/tensor_mux/gsttensormux.h @@ -65,28 +65,54 @@ G_BEGIN_DECLS #define GST_TENSOR_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TENSOR_MUX, GstTensorMux)) #define GST_TENSOR_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TENSOR_MUX, GstTensorMuxClass)) #define GST_TENSOR_MUX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TENSOR_MUX, GstTensorMuxClass)) +#define GST_IS_TENSOR_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TENSOR_MUX)) +#define GST_IS_TENSOR_MUX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TENSOR_MUX)) +#define GST_TENSOR_MUX_CAST(obj)((GstTensorMux*)(obj)) typedef struct _GstTensorMux GstTensorMux; typedef struct _GstTensorMuxClass GstTensorMuxClass; +typedef struct +{ + gboolean have_timestamp_offset; + guint timestamp_offset; + + GstSegment segment; + + gboolean done; + gboolean priority; +} GstTensorMuxPadPrivate; + /** * @brief Tensor Muxer data structure */ struct _GstTensorMux { - GstElement parent; - guint32 num_tensors; + GstElement element; + guint64 byte_count; gboolean silent; GstPad *srcpad; - GList *sinkpad; + GstPad *last_pad; + GstBuffer *outbuffer; + + GString *dimensions; + guint32 num_tensors; + gint rank; + GString *types; + gint framerate_numerator; + gint framerate_denominator; + gboolean first; + GstClockTime last_stop; + gboolean send_stream_start; }; /* - * @brief GstTensroMuxClass inherits GstAggregatorClass + * @brief GstTensroMuxClass inherits GstElementClass */ struct _GstTensorMuxClass { - GstElementClass parent; + GstElementClass parent_class; + /* gboolean (*src_event) (GstTensorMux *tensor_mux, GstEvent *event); */ }; /*