[Load] Add skeleton code for tensor_load
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Tue, 24 Jul 2018 08:13:49 +0000 (17:13 +0900)
committer문지중/동작제어Lab(SR)/Principal Engineer/삼성전자 <jijoong.moon@samsung.com>
Wed, 25 Jul 2018 07:32:07 +0000 (16:32 +0900)
tensor_load element will convert other/tensorsave to other/tensors
or other/tensor

Prepares #322

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
CMakeLists.txt
gst/tensor_saveload/CMakeLists.txt [new file with mode: 0644]
gst/tensor_saveload/tensor_load.c [new file with mode: 0644]
gst/tensor_saveload/tensor_load.h [new file with mode: 0644]

index 5c07206..b7fc832 100644 (file)
@@ -92,6 +92,7 @@ ADD_SUBDIRECTORY(gst/tensor_sink)
 ADD_SUBDIRECTORY(gst/tensor_mux)
 ADD_SUBDIRECTORY(gst/tensor_demux)
 ADD_SUBDIRECTORY(gst/tensor_transform)
+ADD_SUBDIRECTORY(gst/tensor_saveload)
 ADD_SUBDIRECTORY(nnstreamer_example)
 ADD_SUBDIRECTORY(tests/nnstreamer_tensors/tensors_test)
 enable_testing()
diff --git a/gst/tensor_saveload/CMakeLists.txt b/gst/tensor_saveload/CMakeLists.txt
new file mode 100644 (file)
index 0000000..275bda0
--- /dev/null
@@ -0,0 +1,19 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+ADD_LIBRARY(tensor_load SHARED tensor_load.c)
+ADD_LIBRARY(tensor_loadStatic STATIC tensor_load.c)
+
+TARGET_LINK_LIBRARIES(tensor_load ${pkgs_LIBRARIES})
+TARGET_INCLUDE_DIRECTORIES(tensor_load PUBLIC ${pkgs_INCLUDE_DIRS})
+TARGET_COMPILE_OPTIONS(tensor_load PUBLIC ${pkgs_CFLAGS_OTHER})
+TARGET_LINK_LIBRARIES(tensor_loadStatic ${pkgs_LIBRARIES})
+TARGET_INCLUDE_DIRECTORIES(tensor_loadStatic PUBLIC ${pkgs_INCLUDE_DIRS})
+TARGET_COMPILE_OPTIONS(tensor_loadStatic PUBLIC ${pkgs_CFLAGS_OTHER})
+
+INSTALL(TARGETS tensor_load tensor_loadStatic
+       RUNTIME DESTINATION ${EXEC_PREFIX}
+       LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+       ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+       )
+
+## @todo Add tensor_save
diff --git a/gst/tensor_saveload/tensor_load.c b/gst/tensor_saveload/tensor_load.c
new file mode 100644 (file)
index 0000000..ff4324f
--- /dev/null
@@ -0,0 +1,347 @@
+/**
+ * GStreamer
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@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       tensor_load.c
+ * @date       24 Jul 2018
+ * @brief      GStreamer plugin to convert other/tensorsave to other/tensor(s)
+ * @see                http://github.com/nnsuite/nnstreamer
+ * @see                https://github.sec.samsung.net/STAR/nnstreamer
+ * @author     MyungJoo Ham <myungjoo.ham@samsung.com>
+ * @bug                No known bugs except for NYI items
+ *
+ */
+/**
+ * SECTION:element-tensor_load
+ *
+ * Decode other/tensorsave and provide the raw data represented in
+ * other/tensor (if # tensors = 1) or other/tensors (if # tensors > 1).
+ *
+ * @todo NYI: this code supports # tensors = 1 case only!
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v -m filesrc location="test.tnsr" ! tensor_load ! tensor_filter ... ! tensor_sink ...
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gst/gst.h>
+#include <glib.h>
+
+#include "tensor_load.h"
+#include <tensor_meta.h>
+
+GST_DEBUG_CATEGORY_STATIC (gst_tensor_load_debug);
+#define GST_CAT_DEFAULT gst_tensor_load_debug
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_SILENT,
+};
+
+/**
+ * the capabilities of the inputs
+ *
+ * In v0.0.1, this is "bitmap" image stream
+ */
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("other/tensorsave")
+    );
+
+/**
+ * @brief The capabilities of the outputs
+ */
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+    /* This can be both other/tensor and other/tensors */
+
+#define gst_tensor_load_parent_class parent_class
+G_DEFINE_TYPE (GstTensor_Load, gst_tensor_load, GST_TYPE_BASE_TRANSFORM);
+
+static void gst_tensor_load_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_tensor_load_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+/* GstBaseTransformer vmethod implementations */
+static GstFlowReturn gst_tensor_load_transform (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer * outbuf);
+static GstFlowReturn gst_tensor_load_transform_ip (GstBaseTransform *
+    trans, GstBuffer * buf);
+static GstCaps *gst_tensor_load_transform_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter);
+static GstCaps *gst_tensor_load_fixate_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
+static gboolean gst_tensor_load_set_caps (GstBaseTransform * trans,
+    GstCaps * incaps, GstCaps * outcaps);
+static gboolean gst_tensor_load_transform_size (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, gsize size,
+    GstCaps * othercaps, gsize * othersize);
+/* GObject vmethod implementations */
+
+/**
+ * @brief initialize the tensor_load's class
+ */
+static void
+gst_tensor_load_class_init (GstTensor_LoadClass * g_class)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseTransformClass *trans_class;
+  GstTensor_LoadClass *klass;
+
+  klass = (GstTensor_LoadClass *) g_class;
+  trans_class = (GstBaseTransformClass *) klass;
+  gstelement_class = (GstElementClass *) trans_class;
+  gobject_class = (GObjectClass *) gstelement_class;
+
+  gobject_class->set_property = gst_tensor_load_set_property;
+  gobject_class->get_property = gst_tensor_load_get_property;
+
+  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_set_details_simple (gstelement_class,
+      "Tensor_Load",
+      "Convert other/tensorsave to other/tensors or other/tensor",
+      "Convert other/tensorsave to other/tensors or other/tensor if # tensors is 1",
+      "MyungJoo Ham <myungjoo.ham@samsung.com>");
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&src_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sink_factory));
+  /* Refer: https://gstreamer.freedesktop.org/documentation/design/element-transform.html */
+  trans_class->passthrough_on_same_caps = FALSE;
+
+  /* Processing units */
+  trans_class->transform = GST_DEBUG_FUNCPTR (gst_tensor_load_transform);
+  trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_tensor_load_transform_ip);
+
+  /* Negotiation units */
+  trans_class->transform_caps =
+      GST_DEBUG_FUNCPTR (gst_tensor_load_transform_caps);
+  trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_tensor_load_fixate_caps);
+  trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_tensor_load_set_caps);
+
+  /* Allocation units */
+  trans_class->transform_size =
+      GST_DEBUG_FUNCPTR (gst_tensor_load_transform_size);
+}
+
+/**
+ * @brief initialize the new element (G_DEFINE_TYPE requires this)
+ * instantiate pads and add them to element
+ * set pad calback functions
+ * initialize instance structure
+ */
+static void
+gst_tensor_load_init (GstTensor_Load * filter)
+{
+  filter->silent = TRUE;
+
+  filter->num_tensors = 0;
+  filter->dims = NULL;
+  filter->types = NULL;
+  filter->ranks = NULL;
+  filter->framerate_numerator = -1;
+  filter->framerate_denominator = -1;
+  filter->frameSize = 0;
+}
+
+/**
+ * @brief Set property (gst element vmethod)
+ */
+static void
+gst_tensor_load_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstTensor_Load *filter = GST_TENSOR_LOAD (object);
+
+  switch (prop_id) {
+    case PROP_SILENT:
+      filter->silent = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/**
+ * @brief Get property (gst element vmethod)
+ */
+static void
+gst_tensor_load_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstTensor_Load *filter = GST_TENSOR_LOAD (object);
+
+  switch (prop_id) {
+    case PROP_SILENT:
+      g_value_set_boolean (value, filter->silent);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/******************************************************************
+ * GstElement vmethod implementations
+ */
+
+#define return_false_if_fail(x)        \
+  ret = (x); \
+  if (!ret) \
+    return FALSE; \
+  ;
+
+/**
+ * @brief entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and other features
+ */
+static gboolean
+tensor_load_init (GstPlugin * tensor_load)
+{
+  /**
+   * debug category for fltering log messages
+   *
+   * exchange the string 'Template tensor_load' with your description
+   */
+  GST_DEBUG_CATEGORY_INIT (gst_tensor_load_debug, "tensor_load",
+      0, "Template tensor_load");
+
+  return gst_element_register (tensor_load, "tensor_load",
+      GST_RANK_NONE, GST_TYPE_TENSOR_LOAD);
+}
+
+/**
+ * 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 "tensor_load"
+#endif
+
+/**
+ * gstreamer looks for this structure to register tensor_loads
+ *
+ * exchange the string 'Template tensor_load' with your tensor_load description
+ */
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    tensor_load,
+    "tensor_load",
+    tensor_load_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/");
+
+/**
+ * @brief non-ip transform. required vmethod for BaseTransform class.
+ */
+static GstFlowReturn
+gst_tensor_load_transform (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer * outbuf)
+{
+  /** @todo NYI */
+  return GST_FLOW_NOT_SUPPORTED;
+}
+
+/**
+ * @brief in-place transform. required vmethod for BaseTransform class.
+ */
+static GstFlowReturn
+gst_tensor_load_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
+{
+  /** @todo NYI */
+  return GST_FLOW_NOT_SUPPORTED;
+}
+
+/**
+ * @brief configure srcpad cap from "proposed" cap. (required vmethod for BaseTransform)
+ *
+ * @param trans ("this" pointer)
+ * @param direction (why do we need this?)
+ * @param caps sinkpad cap
+ * @param filter this element's cap (don't know specifically.)
+ */
+static GstCaps *
+gst_tensor_load_transform_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+{
+  /** @todo NYI */
+  return NULL;
+}
+
+/**
+ * @brief fixate caps. required vmethod of BaseTransform
+ */
+static GstCaps *
+gst_tensor_load_fixate_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
+{
+  /** @todo NYI */
+  return NULL;
+}
+
+/**
+ * @brief set caps. required vmethod of BaseTransform
+ */
+static gboolean
+gst_tensor_load_set_caps (GstBaseTransform * trans,
+    GstCaps * incaps, GstCaps * outcaps)
+{
+  /** @todo NYI */
+  return FALSE;
+}
+
+/**
+ * @brief Tell the framework the required size of buffer based on the info of the other side pad. optional vmethod of BaseTransform
+ *
+ * We cannot directly get the value from size value, we need to review the pad-caps.
+ * This is called when non-ip mode is used.
+ */
+static gboolean
+gst_tensor_load_transform_size (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, gsize size,
+    GstCaps * othercaps, gsize * othersize)
+{
+  /** @todo NYI */
+  return FALSE;
+}
diff --git a/gst/tensor_saveload/tensor_load.h b/gst/tensor_saveload/tensor_load.h
new file mode 100644 (file)
index 0000000..00225ab
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * GStreamer
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@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       tensor_load.c
+ * @date       24 Jul 2018
+ * @brief      GStreamer plugin to convert other/tensorsave to other/tensor(s)
+ * @see                http://github.com/nnsuite/nnstreamer
+ * @see                https://github.sec.samsung.net/STAR/nnstreamer
+ * @author     MyungJoo Ham <myungjoo.ham@samsung.com>
+ * @bug                No known bugs except for NYI items
+ *
+ */
+
+#ifndef __GST_TENSOR_LOAD_H__
+#define __GST_TENSOR_LOAD_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <tensor_common.h>
+
+G_BEGIN_DECLS
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_TENSOR_LOAD \
+  (gst_tensor_load_get_type())
+#define GST_TENSOR_LOAD(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TENSOR_LOAD,GstTensor_Load))
+#define GST_TENSOR_LOAD_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TENSOR_LOAD,GstTensor_LoadClass))
+#define GST_IS_TENSOR_LOAD(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TENSOR_LOAD))
+#define GST_IS_TENSOR_LOAD_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TENSOR_LOAD))
+#define GST_TENSOR_LOAD_CAST(obj)  ((GstTensor_Load *)(obj))
+typedef struct _GstTensor_Load GstTensor_Load;
+
+typedef struct _GstTensor_LoadClass GstTensor_LoadClass;
+
+/**
+ * @brief Internal data structure for tensor_load instances.
+ */
+struct _GstTensor_Load
+{
+  GstBaseTransform element;     /**< This is the parent object */
+
+  /* For Tensor */
+  gboolean silent;      /**< True if logging is minimized */
+
+  guint num_tensors;    /**< Number of tensors in each frame */
+  tensor_dim *dims;     /**< Array of tensor_dim, [num_tensors] */
+  tensor_type *types;   /**< Array of tensor_type, [num_tensors] */
+  gint *ranks;          /**< Array of rank, [num_tensors] */
+  gint framerate_numerator;     /**< framerate is in fraction, which is numerator/denominator */
+  gint framerate_denominator;   /**< framerate is in fraction, which is numerator/denominator */
+  gsize frameSize;        /**< Size of a frame in # bytes */
+};
+
+/**
+ * @brief GstTensor_LoadClass inherits GstBaseTransformClass.
+ *
+ * Referring another child (sibiling), GstVideoFilter (abstract class) and
+ * its child (concrete class) GstVideoLoad.
+ * Note that GstTensor_LoadClass is a concrete class; thus we need to look at both.
+ */
+struct _GstTensor_LoadClass
+{
+  GstBaseTransformClass parent_class;   /**< Inherits GstBaseTransformClass */
+};
+
+/**
+ * @brief Get Type function required for gst elements
+ */
+GType gst_tensor_load_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_TENSOR_LOAD_H__ */