[TensorSplit] Skeleton to split tensor into multiple tensor
authorjijoong.moon <jijoong.moon@samsung.com>
Mon, 27 Aug 2018 01:53:02 +0000 (10:53 +0900)
committer안형주/언어이해Lab(SR)/Engineer/삼성전자 <hello.ahn@samsung.com>
Mon, 27 Aug 2018 09:15:37 +0000 (18:15 +0900)
In order to split tensor to multiple tensor, tensor_split is
requried. It take one big tensor as an input and push the multiple
smale tensor segment to downstream according to segment option.

This PR indlucdes skeleton of tensor split.

Signed-off-by: jijoong.moon <jijoong.moon@samsung.com>
CMakeLists.txt
gst/tensor_split/CMakeLists.txt [new file with mode: 0644]
gst/tensor_split/gsttensorsplit.c [new file with mode: 0644]
gst/tensor_split/gsttensorsplit.h [new file with mode: 0644]

index fd18ddf..ab6ce19 100644 (file)
@@ -100,6 +100,7 @@ ADD_SUBDIRECTORY(gst/tensor_decoder)
 ADD_SUBDIRECTORY(gst/tensor_sink)
 ADD_SUBDIRECTORY(gst/tensor_mux)
 ADD_SUBDIRECTORY(gst/tensor_demux)
+ADD_SUBDIRECTORY(gst/tensor_split)
 ADD_SUBDIRECTORY(gst/tensor_transform)
 ADD_SUBDIRECTORY(gst/tensor_saveload)
 ADD_SUBDIRECTORY(nnstreamer_example)
diff --git a/gst/tensor_split/CMakeLists.txt b/gst/tensor_split/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c7edb78
--- /dev/null
@@ -0,0 +1,15 @@
+ADD_LIBRARY(tensorsplit SHARED gsttensorsplit.c )
+ADD_LIBRARY(tensorsplitStatic STATIC gsttensorsplit.c)
+
+TARGET_LINK_LIBRARIES(tensorsplit ${pkgs_LIBRARIES})
+TARGET_INCLUDE_DIRECTORIES(tensorsplit PUBLIC ${pkgs_INCLUDE_DIRS})
+TARGET_COMPILE_OPTIONS(tensorsplit PUBLIC ${pkgs_CFLAGS_OTHER})
+TARGET_LINK_LIBRARIES(tensorsplitStatic ${pkgs_LIBRARIES})
+TARGET_INCLUDE_DIRECTORIES(tensorsplitStatic PUBLIC ${pkgs_INCLUDE_DIRS})
+TARGET_COMPILE_OPTIONS(tensorsplitStatic PUBLIC ${pkgs_CFLAGS_OTHER})
+
+INSTALL(TARGETS tensorsplit tensorsplitStatic
+       RUNTIME DESTINATION ${EXEC_PREFIX}
+       LIBRARY DESTINATION ${GST_INSTALL_DIR}
+       ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+       )
diff --git a/gst/tensor_split/gsttensorsplit.c b/gst/tensor_split/gsttensorsplit.c
new file mode 100644 (file)
index 0000000..2f11459
--- /dev/null
@@ -0,0 +1,424 @@
+/**
+ * GStreamer
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2018 Jijoong Moon <jijoong.moon@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ */
+/**
+ * @file       gsttensorsplit.c
+ * @date       03 July 2018
+ * @brief      GStreamer plugin to split tensor (as a filter for other general neural network filters)
+ * @bug         No known bugs
+ *
+ * @see                http://github.com/nnsuite/nnstreamer
+ * @see                https://github.sec.samsung.net/STAR/nnstreamer
+ * @author     Jijoong Moon <jijoong.moon@samsung.com>
+ * @bug                No known bugs except for NYI items
+ *
+ */
+
+/**
+ * SECTION:element-tensorsplit
+ *
+ * A Deuxer that split tensors stream to tensor stream for NN frameworks.
+ * The outputs are always in the format of other/tensor
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * ]|
+ *
+ * </refsect2>
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gst/gst.h>
+#include <glib.h>
+#include <stdlib.h>
+
+#include "gsttensorsplit.h"
+#include <tensor_meta.h>
+
+GST_DEBUG_CATEGORY_STATIC (gst_tensor_split_debug);
+#define GST_CAT_DEFAULT gst_tensor_split_debug
+
+enum
+{
+  PROP_0,
+  PROP_SILENT,
+  PROP_TENSORPICK,
+  PROP_TENSORSEG
+};
+
+/**
+ * @brief the capabilities of the inputs and outputs.
+ * describe the real formats here.
+ */
+static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src_%u",
+    GST_PAD_SRC,
+    GST_PAD_SOMETIMES,
+    GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT)
+    );
+
+static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT)
+    );
+
+static GstFlowReturn gst_tensor_split_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buf);
+static gboolean gst_tensor_split_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static GstStateChangeReturn gst_tensor_split_change_state (GstElement * element,
+    GstStateChange transition);
+static void gst_tensor_split_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_tensor_split_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_tensor_split_dispose (GObject * object);
+#define gst_tensor_split_parent_class parent_class
+G_DEFINE_TYPE (GstTensorSplit, gst_tensor_split, GST_TYPE_ELEMENT);
+
+
+/**
+ * @brief initialize the tensor_split's class
+ */
+static void
+gst_tensor_split_class_init (GstTensorSplitClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->dispose = gst_tensor_split_dispose;
+  gobject_class->get_property = gst_tensor_split_get_property;
+  gobject_class->set_property = gst_tensor_split_set_property;
+
+  g_object_class_install_property (gobject_class, PROP_SILENT,
+      g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
+          FALSE, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_TENSORSEG,
+      g_param_spec_boolean ("segment", "Segment", "How to split tensor ?",
+          FALSE, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_TENSORPICK,
+      g_param_spec_string ("tensorpick", "TensorPick",
+          "Choose nth tensor among tensors ?", "", G_PARAM_READWRITE));
+
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_tensor_split_change_state);
+
+  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));
+
+  gst_element_class_set_details_simple (gstelement_class,
+      "tensorsplit",
+      "Split other/tensor stream",
+      "Split tensor stream to other/tensor stream",
+      "Jijoong Moon <jijoong.moon@samsung.com>");
+}
+
+/**
+ * @brief initialize the new element
+ * instantiate pads and add them to element
+ * set pad calback functions
+ * initialize instance structure
+ */
+static void
+gst_tensor_split_init (GstTensorSplit * tensor_split)
+{
+  tensor_split->sinkpad =
+      gst_pad_new_from_static_template (&sink_templ, "sink");
+  gst_element_add_pad (GST_ELEMENT_CAST (tensor_split), tensor_split->sinkpad);
+  gst_pad_set_chain_function (tensor_split->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_tensor_split_chain));
+  gst_pad_set_event_function (tensor_split->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_tensor_split_event));
+
+  tensor_split->num_tensors = 0;
+  tensor_split->num_srcpads = 0;
+  tensor_split->silent = FALSE;
+  tensor_split->tensorpick = NULL;
+  tensor_split->tensorseg = NULL;
+  tensor_split->have_group_id = FALSE;
+  tensor_split->group_id = G_MAXUINT;
+  tensor_split->srcpads = NULL;
+}
+
+/**
+ * @brief function to remove srcpad list
+ */
+static void
+gst_tensor_split_remove_src_pads (GstTensorSplit * tensor_split)
+{
+  while (tensor_split->srcpads != NULL) {
+    GstTensorPad *tensor_pad = tensor_split->srcpads->data;
+    gst_element_remove_pad (GST_ELEMENT (tensor_split), tensor_pad->pad);
+    g_free (tensor_pad);
+    tensor_split->srcpads =
+        g_slist_delete_link (tensor_split->srcpads, tensor_split->srcpads);
+  }
+  tensor_split->srcpads = NULL;
+  tensor_split->num_tensors = 0;
+  tensor_split->num_srcpads = 0;
+}
+
+/**
+ * @brief dispose function for tensor split (gst element vmethod)
+ */
+static void
+gst_tensor_split_dispose (GObject * object)
+{
+  GstTensorSplit *tensor_split = GST_TENSOR_SPLIT (object);
+
+  gst_tensor_split_remove_src_pads (tensor_split);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/**
+ * @brief Set Caps in pad.
+ * @param tensor_split GstTensorSplit Ojbect
+ * @param caps incomming capablity
+ * @return TRUE/FALSE (if successfully generate & set cap, return TRUE)
+ */
+static gboolean
+gst_tensor_split_get_capsparam (GstTensorSplit * tensor_split, GstCaps * caps)
+{
+  gboolean ret = FALSE;
+
+  return ret;
+}
+
+/**
+ * @brief event function for sink (gst element vmethod)
+ */
+static gboolean
+gst_tensor_split_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+  GstTensorSplit *tensor_split;
+  tensor_split = GST_TENSOR_SPLIT (parent);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+      gst_event_parse_caps (event, &caps);
+      gst_tensor_split_get_capsparam (tensor_split, caps);
+      return gst_pad_event_default (pad, parent, event);
+    }
+    case GST_EVENT_EOS:
+      if (!tensor_split->srcpads) {
+        GST_ELEMENT_ERROR (tensor_split, STREAM, WRONG_TYPE,
+            ("This stream contains no valid stremas."),
+            ("Got EOS before adding any pads"));
+        gst_event_unref (event);
+        return FALSE;
+      } else {
+        return gst_pad_event_default (pad, parent, event);
+      }
+      break;
+    default:
+      return gst_pad_event_default (pad, parent, event);
+  }
+}
+
+/**
+ * @brief chain function for sink (gst element vmethod)
+ */
+static GstFlowReturn
+gst_tensor_split_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+
+  return res;
+}
+
+/**
+ * @brief change state (gst element vmethod)
+ */
+static GstStateChangeReturn
+gst_tensor_split_change_state (GstElement * element, GstStateChange transition)
+{
+  GstTensorSplit *tensor_split;
+  GstStateChangeReturn ret;
+  tensor_split = GST_TENSOR_SPLIT (element);
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      tensor_split->group_id = G_MAXUINT;
+      tensor_split->have_group_id = FALSE;
+      gst_tensor_split_remove_src_pads (tensor_split);
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+/**
+ * @brief Get property (gst element vmethod)
+ */
+static void
+gst_tensor_split_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstTensorSplit *self = GST_TENSOR_SPLIT (object);
+  switch (prop_id) {
+    case PROP_SILENT:
+      self->silent = g_value_get_boolean (value);
+      break;
+    case PROP_TENSORPICK:
+    {
+      gint i;
+      gint64 val;
+      const gchar *param = g_value_get_string (value);
+      gchar **strv = g_strsplit_set (param, ",.;/", -1);
+      gint num = g_strv_length (strv);
+      for (i = 0; i < num; i++) {
+        val = g_ascii_strtoll (strv[i], NULL, 10);
+        self->tensorpick =
+            g_list_append (self->tensorpick, GINT_TO_POINTER (val));
+      }
+      break;
+    }
+    case PROP_TENSORSEG:
+    {
+      gint i;
+      const gchar *param = g_value_get_string (value);
+      gchar **strv = g_strsplit_set (param, ",.;/", -1);
+      self->num_tensors = g_strv_length (strv);
+      self->tensorseg =
+          g_array_sized_new (FALSE, FALSE, sizeof (tensor_dim *),
+          self->num_tensors);
+      for (i = 0; i < self->num_tensors; i++) {
+        gchar **p;
+        gint num, k;
+        tensor_dim *d;
+        p = g_strsplit_set (strv[i], ":", -1);
+        num = g_strv_length (p);
+        d = g_new0 (tensor_dim, 1);
+        for (k = 0; k < num; k++) {
+          (*d)[k] = atoi (p[k]);
+        }
+        g_array_append_val (self->tensorseg, d);
+        g_strfreev (p);
+      }
+      g_strfreev (strv);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/**
+ * @brief Get property (gst element vmethod)
+ */
+static void
+gst_tensor_split_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstTensorSplit *filter = GST_TENSOR_SPLIT (object);
+  switch (prop_id) {
+    case PROP_SILENT:
+      g_value_set_boolean (value, filter->silent);
+      break;
+    case PROP_TENSORPICK:
+    {
+      GList *list;
+      char *p = "";
+      GPtrArray *arr = g_ptr_array_new ();
+      gchar **strings;
+
+      for (list = filter->tensorpick; list != NULL; list = list->next) {
+        g_ptr_array_add (arr, g_strdup_printf ("%i",
+                GPOINTER_TO_INT (list->data)));
+      }
+      g_ptr_array_add (arr, NULL);
+      strings = (gchar **) g_ptr_array_free (arr, FALSE);
+      p = g_strjoinv (",", strings);
+      g_free (strings);
+      g_value_set_string (value, p);
+      break;
+    }
+    case PROP_TENSORSEG:
+    {
+      break;
+    }
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/**
+ * 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 "tensorsplit"
+#endif
+
+/**
+ * @brief entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and other features
+ */
+gboolean
+gst_tensor_split_plugin_init (GstPlugin * tensorsplit)
+{
+  /** debug category for fltering log messages
+   * exchange the string 'Template tensor_split' with your description
+   */
+  GST_DEBUG_CATEGORY_INIT (gst_tensor_split_debug, "tensorsplit", 0,
+      "Tensor Spliter");
+  return gst_element_register (tensorsplit, "tensorsplit",
+      GST_RANK_NONE, GST_TYPE_TENSOR_SPLIT);
+}
+
+/**
+ * @brief gstreamer looks for this structure to register tensorsplit
+ */
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    tensorsplit,
+    "tensorsplit",
+    gst_tensor_split_plugin_init, VERSION, "LGPL", "GStreamer",
+    "http://gstreamer.net/");
diff --git a/gst/tensor_split/gsttensorsplit.h b/gst/tensor_split/gsttensorsplit.h
new file mode 100644 (file)
index 0000000..ba38399
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * GStreamer
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2018 Jijoong Moon <jijoong.moon@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ */
+/**
+ * @file       gsttensorsplit.h
+ * @date       03 July 2018
+ * @brief      GStreamer plugin to split tensor (as a filter for other general neural network filters)
+ * @bug         No known bugs
+ *
+ * @see                http://github.com/nnsuite/nnstreamer
+ * @see                https://github.sec.samsung.net/STAR/nnstreamer
+ * @author     Jijoong Moon <jijoong.moon@samsung.com>
+ * @bug                No known bugs except for NYI items
+ *
+ */
+
+#ifndef __GST_TENSOR_SPLIT_H__
+#define __GST_TENSOR_SPLIT_H__
+
+#include <gst/gst.h>
+#include <tensor_common.h>
+#include <tensor_meta.h>
+
+G_BEGIN_DECLS
+#define GST_TYPE_TENSOR_SPLIT (gst_tensor_split_get_type ())
+#define GST_TENSOR_SPLIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TENSOR_SPLIT, GstTensorSplit))
+#define GST_TENSOR_SPLIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TENSOR_SPLIT, GstTensorSplitClass))
+#define GST_TENSOR_SPLIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TENSOR_SPLIT, GstTensorSplitClass))
+#define GST_IS_TENSOR_SPLIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TENSOR_SPLIT))
+#define GST_IS_TENSOR_SPLIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TENSOR_SPLIT))
+#define GST_TENSOR_SPLIT_CAST(obj)((GstTensorSplit*)(obj))
+typedef struct _GstTensorSplit GstTensorSplit;
+typedef struct _GstTensorSplitClass GstTensorSplitClass;
+
+typedef struct
+{
+  GstPad *pad;
+  GstClockTime last_ts;
+  GstFlowReturn last_ret;
+  gboolean discont;
+  gint nth;
+} GstTensorPad;
+
+/**
+ * @brief Tensor Spliter data structure
+ */
+struct _GstTensorSplit
+{
+  GstElement element;
+
+  gboolean silent;
+  GstPad *sinkpad;
+  GSList *srcpads;
+  guint32 num_tensors;
+  guint32 num_srcpads;
+  GList *tensorpick;
+  GArray *tensorseg;
+  gboolean have_group_id;
+  guint group_id;
+  GstTensorConfig sink_tensor_conf;
+};
+
+/**
+ * @brief GstTensorSplitClass inherits GstElementClass
+ */
+struct _GstTensorSplitClass
+{
+  GstElementClass parent_class;
+};
+
+/**
+ * @brief Get Type function required for gst elements
+ */
+GType gst_tensor_split_get_type (void);
+
+G_END_DECLS
+#endif  /** __GST_TENSOR_SPLIT_H__ **/