[TensorMux] Set Capability & using private date for sink pad
authorjijoong.moon <jijoong.moon@samsung.com>
Tue, 10 Jul 2018 00:35:09 +0000 (09:35 +0900)
committer함명주/동작제어Lab(SR)/Principal Engineer/삼성전자 <myungjoo.ham@samsung.com>
Tue, 10 Jul 2018 04:21:51 +0000 (13:21 +0900)
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 <jijoong.moon@samsung.com>
gst/tensor_mux/gsttensormux.c
gst/tensor_mux/gsttensormux.h

index 1746157..2611147 100644 (file)
 #include "gsttensormux.h"
 #include <tensor_meta.h>
 
-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/");
index 9a6f139..f229b7a 100644 (file)
@@ -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); */
 };
 
 /*