[Decoder] Add flex buffer decoder
authorGichan Jang <gichan2.jang@samsung.com>
Thu, 11 Mar 2021 08:00:46 +0000 (17:00 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Wed, 24 Mar 2021 05:40:04 +0000 (14:40 +0900)
Add tensor decoder subplugin offlexbuffer.
Decode tensor(s) to flexbuffer.

Signed-off-by: Gichan Jang <gichan2.jang@samsung.com>
debian/nnstreamer-flatbuf.install
ext/nnstreamer/tensor_decoder/meson.build
ext/nnstreamer/tensor_decoder/tensordec-flexbuf.cc [new file with mode: 0644]
gst/nnstreamer/include/tensor_typedef.h
packaging/nnstreamer.spec

index 40971f9..ec4dda5 100644 (file)
@@ -1,2 +1,3 @@
 /usr/lib/nnstreamer/converters/libnnstreamer_converter_flatbuf.so
 /usr/lib/nnstreamer/decoders/libnnstreamer_decoder_flatbuf.so
+/usr/lib/nnstreamer/decoders/libnnstreamer_decoder_flexbuf.so
index 01081a8..4477cf8 100644 (file)
@@ -131,7 +131,7 @@ if protobuf_support_is_available
   foreach s : decoder_sub_protobuf_sources
     nnstreamer_decoder_protobuf_sources += join_paths(meson.current_source_dir(), s)
   endforeach
-  
+
   shared_library('nnstreamer_decoder_protobuf',
     nnstreamer_decoder_protobuf_sources,
     dependencies: [nnstreamer_dep, glib_dep, gst_dep, protobuf_util_dep],
@@ -150,7 +150,7 @@ if flatbuf_support_is_available
   nnstreamer_decoder_flatbuf_sources = [fb_gen_src]
   foreach s : decoder_sub_flatbuf_sources
     nnstreamer_decoder_flatbuf_sources += join_paths(meson.current_source_dir(), s)
-  endforeach  
+  endforeach
 
   shared_library('nnstreamer_decoder_flatbuf',
     nnstreamer_decoder_flatbuf_sources,
@@ -158,4 +158,21 @@ if flatbuf_support_is_available
     install: true,
     install_dir: decoder_subplugin_install_dir,
   )
+
+  decoder_sub_flexbuf_sources = [
+    'tensordec-flexbuf.cc',
+    'tensordecutil.c'
+  ]
+
+  nnstreamer_decoder_flexbuf_sources = []
+  foreach s : decoder_sub_flexbuf_sources
+    nnstreamer_decoder_flexbuf_sources += join_paths(meson.current_source_dir(), s)
+  endforeach
+
+  shared_library('nnstreamer_decoder_flexbuf',
+    nnstreamer_decoder_flexbuf_sources,
+    dependencies: [nnstreamer_dep, glib_dep, gst_dep, flatbuf_dep],
+    install: true,
+    install_dir: decoder_subplugin_install_dir,
+  )
 endif
diff --git a/ext/nnstreamer/tensor_decoder/tensordec-flexbuf.cc b/ext/nnstreamer/tensor_decoder/tensordec-flexbuf.cc
new file mode 100644 (file)
index 0000000..20642d5
--- /dev/null
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/**
+ * GStreamer / NNStreamer tensor_decoder subplugin, "Flexbuffer"
+ * Copyright (C) 2021 Gichan Jang <gichan2.jang@samsung.com>
+ */
+/**
+ * @file        tensordec-flexbuf.cc
+ * @date        12 Mar 2021
+ * @brief       NNStreamer tensor-decoder subplugin, "flexbuffer",
+ *              which converts tensor or tensors to flexbuffer byte stream.
+ *
+ * @see         https://github.com/nnstreamer/nnstreamer
+ * @author      Gichan Jang <gichan2.jang@samsung.com>
+ * @bug         No known bugs except for NYI items
+ *
+ */
+/**
+ * SECTION:tensor_decoder::flexbuf
+ * @see https://google.github.io/flatbuffers/flexbuffers.html
+ *
+ * tensor_decoder::flexbuf converts tensors stream to flexbuffers.
+ *
+ * Binary format of the flexbuffers for tensors (default in nnstreamer).
+ * Each data is represented in `KEY : TYPE | <VALUE>` form.
+ *
+ * Map {
+ *   "num_tensors" : UInt32 | <The number of tensors>
+ *   "rate_n" : Int32 | <Framerate numerator>
+ *   "rate_d" : Int32 | <Framerate denominator>
+ *   "tensor_#": Vector | { String | <tensor name>,
+ *                          Int32 | <data type>,
+ *                          Vector | <tensor dimension>,
+ *                          Blob | <tensor data>
+ *                         }
+ * }
+ */
+
+
+#include <glib.h>
+#include <nnstreamer_log.h>
+#include <nnstreamer_plugin_api.h>
+#include <nnstreamer_plugin_api_decoder.h>
+#include "tensordecutil.h"
+#include <flatbuffers/flexbuffers.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+void init_flxb (void) __attribute__ ((constructor));
+void fini_flxb (void) __attribute__ ((destructor));
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static int
+flxb_init (void **pdata)
+{
+  *pdata = NULL;
+  return TRUE;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static void
+flxb_exit (void **pdata)
+{
+  return;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static int
+flxb_setOption (void **pdata, int opNum, const char *param)
+{
+  return TRUE;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static GstCaps *
+flxb_getOutCaps (void **pdata, const GstTensorsConfig *config)
+{
+  GstCaps *caps;
+  caps = gst_caps_from_string (GST_FLEXBUF_CAP_DEFAULT);
+  setFramerateFromConfig (caps, config);
+  return caps;
+}
+
+/** @brief tensordec-plugin's GstTensorDecoderDef callback */
+static GstFlowReturn
+flxb_decode (void **pdata, const GstTensorsConfig *config,
+    const GstTensorMemory *input, GstBuffer *outbuf)
+{
+  GstMapInfo out_info;
+  GstMemory *out_mem;
+  unsigned int i, num_tensors = config->info.num_tensors;
+  gboolean need_alloc;
+  size_t flex_size;
+  flexbuffers::Builder fbb;
+
+  fbb.Map ([&]() {
+    fbb.UInt ("num_tensors", num_tensors);
+    fbb.Int ("rate_n", config->rate_n);
+    fbb.Int ("rate_d", config->rate_d);
+    for (i = 0; i < num_tensors; i++) {
+      gchar * tensor_key = g_strdup_printf ("tensor_%d", i);
+      gchar * tensor_name = NULL;
+
+      if (config->info.info[i].name == NULL) {
+        tensor_name = g_strdup ("");
+      } else {
+        tensor_name = g_strdup (config->info.info[i].name);
+      }
+      tensor_type type = config->info.info[i].type;
+
+      fbb.Vector (tensor_key, [&]() {
+        fbb += tensor_name;
+        fbb += type;
+        fbb.Vector (config->info.info[i].dimension, NNS_TENSOR_RANK_LIMIT);
+        fbb.Blob (input[i].data, (size_t) input[i].size);
+      });
+      g_free (tensor_key);
+      g_free (tensor_name);
+    }
+  });
+  fbb.Finish ();
+  flex_size = fbb.GetSize ();
+
+  g_assert (outbuf);
+  need_alloc = (gst_buffer_get_size (outbuf) == 0);
+
+  if (need_alloc) {
+    out_mem = gst_allocator_alloc (NULL, flex_size, NULL);
+  } else {
+    if (gst_buffer_get_size (outbuf) < flex_size) {
+      gst_buffer_set_size (outbuf, flex_size);
+    }
+    out_mem = gst_buffer_get_all_memory (outbuf);
+  }
+
+  if (FALSE == gst_memory_map (out_mem, &out_info, GST_MAP_WRITE)) {
+    if (need_alloc)
+      gst_allocator_free (NULL, out_mem);
+    nns_loge ("Cannot map gst memory (tensor decoder flexbuf)\n");
+    return GST_FLOW_ERROR;
+  }
+
+  memcpy (out_info.data, fbb.GetBuffer ().data (), flex_size);
+
+  gst_memory_unmap (out_mem, &out_info);
+
+  if (need_alloc)
+    gst_buffer_append_memory (outbuf, out_mem);
+
+  return GST_FLOW_OK;
+}
+
+static gchar decoder_subplugin_flexbuf[] = "flexbuf";
+
+/** @brief flexbuffer tensordec-plugin GstTensorDecoderDef instance */
+static GstTensorDecoderDef flexBuf = {.modename = decoder_subplugin_flexbuf,
+  .init = flxb_init,
+  .exit = flxb_exit,
+  .setOption = flxb_setOption,
+  .getOutCaps = flxb_getOutCaps,
+  .decode = flxb_decode };
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** @brief Initialize this object for tensordec-plugin */
+void
+init_flxb (void)
+{
+  nnstreamer_decoder_probe (&flexBuf);
+}
+
+/** @brief Destruct this object for tensordec-plugin */
+void
+fini_flxb (void)
+{
+  nnstreamer_decoder_exit (flexBuf.modename);
+}
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
index 817c059..9e6e2ec 100644 (file)
     "framerate = " GST_TENSOR_RATE_RANGE
 
 /**
+ * @brief Default static capability for flexbuffers
+ */
+#define GST_FLEXBUF_CAP_DEFAULT "other/flexbuf"
+
+/**
  * @brief Possible data element types of other/tensor.
  */
 typedef enum _nns_tensor_type
index 9cc674e..ad42774 100644 (file)
@@ -834,6 +834,7 @@ cp -r result %{buildroot}%{_datadir}/nnstreamer/unittest/
 %defattr(-,root,root,-)
 %{_prefix}/lib/nnstreamer/decoders/libnnstreamer_decoder_flatbuf.so
 %{_prefix}/lib/nnstreamer/converters/libnnstreamer_converter_flatbuf.so
+%{_prefix}/lib/nnstreamer/decoders/libnnstreamer_decoder_flexbuf.so
 %endif
 
 # for pytorch