[Repo/Push] Use Has Table to handle repo & add slot_id property
authorjijoong.moon <jijoong.moon@samsung.com>
Wed, 21 Nov 2018 01:46:32 +0000 (10:46 +0900)
committerMyungJoo Ham <myungjoo.ham@gmail.com>
Fri, 23 Nov 2018 18:34:27 +0000 (18:34 +0000)
- Instead of single linked list, Hash table is used to manage repo's
  data. Hash Table is "key [slot_id], GstTensorData*" where slot_id is
  given by user when the tensor_repopush is used.

- Slot Id is added to use as key for hash table. This should be same
  with tensor_repopop element. "tensor_repopop" will withdraw the data
  according to this slot_id.

**Self evaluation:**
1. Build test:  [X]Passed [ ]Failed [ ]Skipped
2. Run test:  [X]Passed [ ]Failed [ ]Skipped

Signed-off-by: jijoong.moon <jijoong.moon@samsung.com>
gst/nnstreamer/tensor_repo.c
gst/nnstreamer/tensor_repo.h
gst/tensor_repopush/tensor_repopush.c
gst/tensor_repopush/tensor_repopush.h

index 6e44032..c2e8c51 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * NNStreamer Common Header
+ * NNStreamer Tensor Repo Header's Contents
  * Copyright (C) 2018 Jijoong Moon <jijoong.moon@samsung.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -16,7 +16,7 @@
 /**
  * @file       tensor_repo.c
  * @date       17 Nov 2018
- * @brief      tensor repo header file for NNStreamer, the GStreamer plugin for neural networks
+ * @brief      tensor repo file for NNStreamer, the GStreamer plugin for neural networks
  * @see                https://github.com/nnsuite/nnstreamer
  * @author     Jijoong Moon <jijoong.moon@samsung.com>
  * @bug                No known bugs except for NYI items
  */
 
 #include<tensor_repo.h>
+#include <stdio.h>
+
+#ifndef DBG
+#define DBG TRUE
+#endif
+
+#define _print_log(...) if (DBG) g_message(__VA_ARGS__)
 
 /**
  * @brief tensor repo global variable with init.
  */
-GstTensorRepo _repo = {.num_data = 0,.tensorsdata = NULL,.initialized = FALSE };
+GstTensorRepo _repo = {.num_data = 0,.initialized = FALSE };
 
 /**
  * @brief getter to get nth GstTensorData
@@ -36,35 +43,50 @@ GstTensorRepo _repo = {.num_data = 0,.tensorsdata = NULL,.initialized = FALSE };
 GstTensorData *
 gst_tensor_repo_get_tensor (guint nth)
 {
-  return g_slist_nth_data (_repo.tensorsdata, nth);
+  GstTensorData *data;
+  gpointer *p = g_hash_table_lookup (_repo.hash, GINT_TO_POINTER (nth));
+  data = (GstTensorData *) p;
+  g_return_val_if_fail (data != NULL, NULL);
+  return data;
 }
 
 /**
  * @brief add GstTensorData into repo
  */
-guint
-gst_tensor_repo_add_data (GstTensorData * data)
+gboolean
+gst_tensor_repo_add_data (GstTensorData * data, guint myid)
 {
-  guint id = _repo.num_data;
+  gboolean ret = FALSE;
+
+  if (!_repo.initialized)
+    gst_tensor_repo_init ();
+
   GST_REPO_LOCK ();
-  _repo.tensorsdata = g_slist_append (_repo.tensorsdata, data);
+  ret = g_hash_table_insert (_repo.hash, GINT_TO_POINTER (myid), data);
+  g_assert (ret);
+
+  _print_log ("Successfully added in hash table with key[%d]", myid);
+
   _repo.num_data++;
   GST_REPO_UNLOCK ();
-  return id;
+  return ret;
 }
 
 /**
  * @brief push GstBuffer into repo
  */
-void
+gboolean
 gst_tensor_repo_push_buffer (guint nth, GstBuffer * buffer)
 {
   GST_TENSOR_REPO_LOCK (nth);
 
   GstTensorData *data = gst_tensor_repo_get_tensor (nth);
+  g_return_val_if_fail (data != NULL, FALSE);
+
   data->buffer = buffer;
   GST_TENSOR_REPO_BROADCAST (nth);
   GST_TENSOR_REPO_UNLOCK (nth);
+  return TRUE;
 }
 
 /**
@@ -76,7 +98,7 @@ gst_tensor_repopop_buffer (guint nth)
   GST_TENSOR_REPO_LOCK (nth);
   GstTensorData *current_data, *data;
 
-  current_data = g_slist_nth_data (_repo.tensorsdata, nth);
+  current_data = gst_tensor_repo_get_tensor (nth);
 
   while (!current_data)
     GST_TENSOR_REPO_WAIT (nth);
@@ -90,16 +112,23 @@ gst_tensor_repopop_buffer (guint nth)
 /**
  * @brief remove nth GstTensorData from GstTensorRepo
  */
-void
+gboolean
 gst_tensor_repo_remove_data (guint nth)
 {
+  gboolean ret;
   GST_REPO_LOCK ();
-  GSList *data = g_slist_nth (_repo.tensorsdata, nth);
   g_mutex_clear (GST_TENSOR_REPO_GET_LOCK (nth));
   g_cond_clear (GST_TENSOR_REPO_GET_COND (nth));
-  _repo.tensorsdata = g_slist_delete_link (_repo.tensorsdata, data);
-  _repo.num_data--;
+
+  ret = g_hash_table_remove (_repo.hash, GINT_TO_POINTER (nth));
+
+  if (ret) {
+    _repo.num_data--;
+    _print_log ("key[%d] is removed\n", nth);
+  }
+
   GST_REPO_UNLOCK ();
+  return ret;
 }
 
 /**
@@ -110,6 +139,6 @@ gst_tensor_repo_init ()
 {
   _repo.num_data = 0;
   g_mutex_init (&_repo.repo_lock);
-  _repo.tensorsdata = NULL;
+  _repo.hash = g_hash_table_new (g_direct_hash, g_direct_equal);
   _repo.initialized = TRUE;
 }
index 1474965..2468e4d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * NNStreamer Common Header
+ * NNStreamer Tensor Repo Header
  * Copyright (C) 2018 Jijoong Moon <jijoong.moon@samsung.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -39,6 +39,7 @@ G_BEGIN_DECLS
  * GstTensorRepo has GSlist of GstTensorData.
  *
  */
+
 typedef struct
 {
   GstTensorConfig *config;
@@ -50,15 +51,13 @@ typedef struct
 /**
  * @brief GstTensorRepo data structure.
  */
-struct GstTensorRepo_s
+typedef struct
 {
   gint num_data;
   GMutex repo_lock;
-  GSList *tensorsdata;
+  GHashTable* hash;
   gboolean initialized;
-};
-
-typedef struct GstTensorRepo_s GstTensorRepo;
+} GstTensorRepo;
 
 /**
  * @brief getter to get nth GstTensorData
@@ -66,26 +65,36 @@ typedef struct GstTensorRepo_s GstTensorRepo;
 GstTensorData *
 gst_tensor_repo_get_tensor (guint nth);
 
-guint
-gst_tensor_repo_add_data(GstTensorData *data);
+/**
+ * @brief add GstTensorData into repo
+ */
+/* guint */
+gboolean
+gst_tensor_repo_add_data (GstTensorData * data, guint myid);
 
-void
-gst_tensor_repo_push_buffer(guint nth, GstBuffer *buffer);
+/**
+ * @brief push GstBuffer into repo
+ */
+gboolean
+gst_tensor_repo_push_buffer (guint nth, GstBuffer * buffer);
 
+/**
+ * @brief pop GstTensorData from repo
+ */
 GstTensorData *
-gst_tensor_repopop_buffer(guint nth);
+gst_tensor_repopop_buffer (guint nth);
 
 /**
  * @brief remove nth GstTensorData from GstTensorRepo
  */
-void
+gboolean
 gst_tensor_repo_remove_data (guint nth);
 
 /**
  * @brief GstTensorRepo initialization
  */
 void
-gst_tensor_repo_init();
+gst_tensor_repo_init ();
 
 
 /**
index 6dd34dc..cde3af7 100644 (file)
 #include "tensor_repopush.h"
 
 /**
- * @brief Macro for debug mode.
- */
-#ifndef DBG
-#define DBG (!self->silent)
-#endif
-
-/**
  * @brief tensor repository
  */
 extern GstTensorRepo _repo;
 
-/**
- * @brief Macro for debug message.
- */
-#define silent_debug(...) \
-    debug_print (DBG, __VA_ARGS__)
 
 GST_DEBUG_CATEGORY_STATIC (gst_tensor_repopush_debug);
 #define GST_CAT_DEFAULT gst_tensor_repopush_debug
@@ -62,12 +50,14 @@ enum
 {
   PROP_0,
   PROP_SIGNAL_RATE,
+  PROP_SLOT,
   PROP_SILENT
 };
 
 #define DEFAULT_SIGNAL_RATE 0
 #define DEFAULT_SILENT TRUE
 #define DEFAULT_QOS TRUE
+#define DEFAULT_INDEX 0
 
 /**
  * @brief tensor_repopush sink template
@@ -122,6 +112,11 @@ gst_tensor_repopush_class_init (GstTensorRepoPushClass * klass)
           "New data signals per second (0 for unlimited, max 500)", 0, 500,
           DEFAULT_SIGNAL_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_SLOT,
+      g_param_spec_uint ("slot-index", "Slot Index", "repository slot index",
+          0, UINT_MAX, DEFAULT_INDEX,
+          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",
           DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
@@ -150,19 +145,19 @@ gst_tensor_repopush_class_init (GstTensorRepoPushClass * klass)
 static void
 gst_tensor_repopush_init (GstTensorRepoPush * self)
 {
+  gboolean ret = FALSE;
   GstBaseSink *basesink;
   basesink = GST_BASE_SINK (self);
 
-  if (!_repo.initialized)
-    gst_tensor_repo_init ();
-
   self->data.config = NULL;
   self->data.buffer = NULL;
 
   g_mutex_init (&self->data.lock);
   g_cond_init (&self->data.cond);
 
-  self->myid = gst_tensor_repo_add_data (&self->data);
+  ret = gst_tensor_repo_add_data (&self->data, self->myid);
+  g_assert (ret);
+
 
   self->silent = DEFAULT_SILENT;
   self->signal_rate = DEFAULT_SIGNAL_RATE;
@@ -189,6 +184,9 @@ gst_tensor_repopush_set_property (GObject * object, guint prop_id,
     case PROP_SILENT:
       self->silent = g_value_get_boolean (value);
       break;
+    case PROP_SLOT:
+      self->myid = g_value_get_uint (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -211,6 +209,9 @@ gst_tensor_repopush_get_property (GObject * object, guint prop_id,
     case PROP_SILENT:
       g_value_set_boolean (value, self->silent);
       break;
+    case PROP_SLOT:
+      g_value_set_uint (value, self->myid);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -223,9 +224,13 @@ gst_tensor_repopush_get_property (GObject * object, guint prop_id,
 static void
 gst_tensor_repopush_dispose (GObject * object)
 {
+  gboolean ret;
   GstTensorRepoPush *self;
   self = GST_TENSOR_REPOPUSH (object);
-  gst_tensor_repo_remove_data (self->myid);
+  ret = gst_tensor_repo_remove_data (self->myid);
+  if (!ret)
+    GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
+        ("Cannot remove [key: %d] in repo", self->myid), NULL);
 }
 
 /**
@@ -252,14 +257,11 @@ gst_tensor_repopush_stop (GstBaseSink * sink)
 static gboolean
 gst_tensor_repopush_query (GstBaseSink * sink, GstQuery * query)
 {
-  GstTensorRepoPush *self;
   GstQueryType type;
   GstFormat format;
 
-  self = GST_TENSOR_REPOPUSH (sink);
   type = GST_QUERY_TYPE (query);
 
-  silent_debug ("received query %s", GST_QUERY_TYPE_NAME (query));
   switch (type) {
     case GST_QUERY_SEEKING:
       /** tensor sink does not support seeking */
@@ -306,8 +308,12 @@ gst_tensor_repopush_render_buffer (GstTensorRepoPush * self, GstBuffer * buffer)
   }
 
   if (notify) {
+    gboolean ret = FALSE;
     self->last_render_time = now;
-    gst_tensor_repo_push_buffer (self->myid, buffer);
+    ret = gst_tensor_repo_push_buffer (self->myid, buffer);
+    if (!ret)
+      GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
+          ("Cannot push buffer into repo [key: %d]", self->myid), NULL);
   }
 }
 
@@ -361,21 +367,6 @@ gst_tensor_repopush_set_caps (GstBaseSink * sink, GstCaps * caps)
   gst_caps_replace (&self->in_caps, caps);
   GST_TENSOR_REPO_UNLOCK (self->myid);
 
-  if (DBG) {
-    guint caps_size, i;
-
-    caps_size = gst_caps_get_size (caps);
-    silent_debug ("set caps, size is %d", caps_size);
-
-    for (i = 0; i < caps_size; i++) {
-      GstStructure *structure = gst_caps_get_structure (caps, i);
-      gchar *str = gst_structure_to_string (structure);
-
-      silent_debug ("[%d] %s", i, str);
-      g_free (str);
-    }
-  }
-
   return TRUE;
 }
 
@@ -419,27 +410,3 @@ NNSTREAMER_PLUGIN_INIT (tensor_repopush)
   return gst_element_register (plugin, "tensor_repopush",
       GST_RANK_NONE, GST_TYPE_TENSOR_REPOPUSH);
 }
-
-#ifndef SINGLE_BINARY
-/**
- * @brief Definition for identifying tensor_sink plugin.
- *
- * 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 "nnstreamer"
-#endif
-
-/**
- * @brief Macro to define the entry point of the plugin.
- */
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    tensor_repopush,
-    "Push element to handle tensor repository",
-    gst_tensor_repopush_plugin_init, VERSION, "LGPL", "nnstreamer",
-    "https://github.com/nnsuite/nnstreamer");
-#endif
index 31840a3..b688220 100644 (file)
@@ -61,6 +61,7 @@ struct _GstTensorRepoPush
   GstCaps *in_caps;
   GstTensorData data;
   guint myid;
+  guint slot_index;
 
 };