From: jijoong.moon Date: Thu, 22 Nov 2018 06:02:28 +0000 (+0900) Subject: [Repo/Push-Pop] Implement NYI part of tensor_reppop. X-Git-Tag: v0.0.3~28 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f5579c6f8d3f6cfd493929daecf306ec889d6550;p=platform%2Fupstream%2Fnnstreamer.git [Repo/Push-Pop] Implement NYI part of tensor_reppop. - Implement NYI part of tensor_reppop. It's parent element is GstPushSrcClass and it's relevant vm functions are implemented such as (create*). - Several utility functions of tensor_repo is newly implemented. - Some changes are made to handle thread synchronization. **Self evaluation:** 1. Build test: [X]Passed [ ]Failed [ ]Skipped 2. Run test: [X]Passed [ ]Failed [ ]Skipped Signed-off-by: jijoong.moon --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c3f481b..5bf6ef0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ SET(PROJECTS tensor_transform tensor_filter tensor_repopush + tensor_repopop ) ADD_SUBDIRECTORY(nnstreamer_example) diff --git a/gst/nnstreamer/nnstreamer.c b/gst/nnstreamer/nnstreamer.c index 0ce12f9..20fa59b 100644 --- a/gst/nnstreamer/nnstreamer.c +++ b/gst/nnstreamer/nnstreamer.c @@ -41,6 +41,7 @@ NNSTREAMER_PLUGIN (tensor_split); NNSTREAMER_PLUGIN (tensor_transform); NNSTREAMER_PLUGIN (tensor_filter); NNSTREAMER_PLUGIN (tensor_repopush); +NNSTREAMER_PLUGIN (tensor_repopop); #define NNSTREAMER_INIT(name, plugin) \ do { \ @@ -67,6 +68,7 @@ gst_nnstreamer_init (GstPlugin * plugin) NNSTREAMER_INIT (tensor_transform, plugin); NNSTREAMER_INIT (tensor_filter, plugin); NNSTREAMER_INIT (tensor_repopush, plugin); + NNSTREAMER_INIT (tensor_repopop, plugin); return TRUE; } diff --git a/gst/nnstreamer/tensor_repo.c b/gst/nnstreamer/tensor_repo.c index 61f342b..422119e 100644 --- a/gst/nnstreamer/tensor_repo.c +++ b/gst/nnstreamer/tensor_repo.c @@ -27,7 +27,7 @@ #include #ifndef DBG -#define DBG TRUE +#define DBG FALSE #endif #define _print_log(...) if (DBG) g_message(__VA_ARGS__) @@ -54,15 +54,25 @@ gst_tensor_repo_get_tensor (guint nth) * @brief add GstTensorData into repo */ gboolean -gst_tensor_repo_add_data (GstTensorData * data, guint myid) +gst_tensor_repo_add_data (guint myid) { gboolean ret = FALSE; - - if (!_repo.initialized) - gst_tensor_repo_init (); + GstTensorData *new; GST_REPO_LOCK (); - ret = g_hash_table_insert (_repo.hash, GINT_TO_POINTER (myid), data); + gpointer *check = g_hash_table_lookup (_repo.hash, GINT_TO_POINTER (myid)); + + if (check != NULL) { + return TRUE; + } + + new = g_new (GstTensorData, 1); + new->eos = FALSE; + new->buffer = NULL; + g_cond_init (&new->cond); + g_mutex_init (&new->lock); + + ret = g_hash_table_insert (_repo.hash, GINT_TO_POINTER (myid), new); g_assert (ret); _print_log ("Successfully added in hash table with key[%d]", myid); @@ -84,31 +94,60 @@ gst_tensor_repo_push_buffer (guint nth, GstBuffer * buffer) g_return_val_if_fail (data != NULL, FALSE); data->buffer = buffer; - _print_log ("Buffer Updated : Buffer Size[%lu]\n", + _print_log ("Pushed [%d] (size : %lu)\n", nth, gst_buffer_get_size (data->buffer)); - GST_TENSOR_REPO_BROADCAST (nth); + + GST_TENSOR_REPO_SIGNAL (nth); GST_TENSOR_REPO_UNLOCK (nth); return TRUE; } /** + * @brief check eos of slot + */ +gboolean +gst_tensor_repo_check_eos (guint nth) +{ + GST_TENSOR_REPO_LOCK (nth); + GstTensorData *data = gst_tensor_repo_get_tensor (nth); + GST_TENSOR_REPO_UNLOCK (nth); + return data->eos; +} + +/** + * @brief set eos of slot + */ +gboolean +gst_tensor_repo_set_eos (guint nth) +{ + GST_TENSOR_REPO_LOCK (nth); + GstTensorData *data = gst_tensor_repo_get_tensor (nth); + data->eos = TRUE; + GST_TENSOR_REPO_UNLOCK (nth); + return data->eos; +} + + +/** * @brief pop GstTensorData from repo */ -GstTensorData * +GstBuffer * gst_tensor_repopop_buffer (guint nth) { - GST_TENSOR_REPO_LOCK (nth); - GstTensorData *current_data, *data; + GstTensorData *current_data; + GstBuffer *buf; current_data = gst_tensor_repo_get_tensor (nth); - while (!current_data) + GST_TENSOR_REPO_LOCK (nth); + while (!current_data->buffer) GST_TENSOR_REPO_WAIT (nth); - data = current_data; - current_data = NULL; + buf = gst_buffer_copy_deep (current_data->buffer); + _print_log ("Popped [ %d ] (size: %lu)\n", nth, gst_buffer_get_size (buf)); + current_data->buffer = NULL; GST_TENSOR_REPO_UNLOCK (nth); - return data; + return buf; } /** @@ -139,8 +178,28 @@ gst_tensor_repo_remove_data (guint nth) void gst_tensor_repo_init () { + if (_repo.initialized) + return; + _repo.num_data = 0; g_mutex_init (&_repo.repo_lock); + g_cond_init (&_repo.repo_cond); + GST_REPO_LOCK (); _repo.hash = g_hash_table_new (g_direct_hash, g_direct_equal); _repo.initialized = TRUE; + GST_REPO_BROADCAST (); + GST_REPO_UNLOCK (); +} + +/** + * @brief wait for finish of initialization + */ +gboolean +gst_tensor_repo_wait () +{ + GST_REPO_LOCK (); + while (!_repo.initialized) + GST_REPO_WAIT (); + GST_REPO_UNLOCK (); + return TRUE; } diff --git a/gst/nnstreamer/tensor_repo.h b/gst/nnstreamer/tensor_repo.h index 2468e4d..82f6d41 100644 --- a/gst/nnstreamer/tensor_repo.h +++ b/gst/nnstreamer/tensor_repo.h @@ -42,10 +42,10 @@ G_BEGIN_DECLS typedef struct { - GstTensorConfig *config; GstBuffer *buffer; GCond cond; GMutex lock; + gboolean eos; } GstTensorData; /** @@ -55,6 +55,7 @@ typedef struct { gint num_data; GMutex repo_lock; + GCond repo_cond; GHashTable* hash; gboolean initialized; } GstTensorRepo; @@ -70,7 +71,7 @@ gst_tensor_repo_get_tensor (guint nth); */ /* guint */ gboolean -gst_tensor_repo_add_data (GstTensorData * data, guint myid); +gst_tensor_repo_add_data (guint myid); /** * @brief push GstBuffer into repo @@ -79,9 +80,21 @@ gboolean gst_tensor_repo_push_buffer (guint nth, GstBuffer * buffer); /** + * @brief get EOS + */ +gboolean +gst_tensor_repo_check_eos(guint nth); + +/** + * @brief set EOS + */ +gboolean +gst_tensor_repo_set_eos(guint nth); + +/** * @brief pop GstTensorData from repo */ -GstTensorData * +GstBuffer * gst_tensor_repopop_buffer (guint nth); /** @@ -96,6 +109,12 @@ gst_tensor_repo_remove_data (guint nth); void gst_tensor_repo_init (); +/** + * @brief Wait for the repo initialization + */ +gboolean +gst_tensor_repo_wait(); + /** * @brief Macro for Lock & Cond @@ -105,9 +124,11 @@ gst_tensor_repo_init (); #define GST_TENSOR_REPO_LOCK(id) (g_mutex_lock(GST_TENSOR_REPO_GET_LOCK(id))) #define GST_TENSOR_REPO_UNLOCK(id) (g_mutex_unlock(GST_TENSOR_REPO_GET_LOCK(id))) #define GST_TENSOR_REPO_WAIT(id) (g_cond_wait(GST_TENSOR_REPO_GET_COND(id), GST_TENSOR_REPO_GET_LOCK(id))) -#define GST_TENSOR_REPO_BROADCAST(id) (g_cond_broadcast (GST_TENSOR_REPO_GET_COND(id))) +#define GST_TENSOR_REPO_SIGNAL(id) (g_cond_signal (GST_TENSOR_REPO_GET_COND(id))) #define GST_REPO_LOCK()(g_mutex_lock(&_repo.repo_lock)) #define GST_REPO_UNLOCK()(g_mutex_unlock(&_repo.repo_lock)) +#define GST_REPO_WAIT() (g_cond_wait(&_repo.repo_cond, &_repo.repo_lock)) +#define GST_REPO_BROADCAST() (g_cond_broadcast (&_repo.repo_cond)) G_END_DECLS #endif /* __GST_TENSOR_REPO_H__ */ diff --git a/gst/tensor_repopop/tensor_repopop.c b/gst/tensor_repopop/tensor_repopop.c index 9bf13a6..ed3c82c 100644 --- a/gst/tensor_repopop/tensor_repopop.c +++ b/gst/tensor_repopop/tensor_repopop.c @@ -57,11 +57,16 @@ enum { PROP_0, PROP_CAPS, + PROP_SLOT_ID, PROP_SILENT }; #define DEFAULT_SILENT TRUE +#define DEFAULT_INDEX 0 +/** + * @brief external repo + */ extern GstTensorRepo _repo; /** @@ -77,19 +82,23 @@ static void gst_tensor_repopop_set_property (GObject * object, guint prop_id, static void gst_tensor_repopop_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_tensor_repopop_dispose (GObject * object); -static gboolean gst_tensor_repopop_query (GstBaseSrc * src, GstQuery * query); static GstCaps *gst_tensor_repopop_getcaps (GstBaseSrc * src, GstCaps * filter); +static GstFlowReturn gst_tensor_repopop_create (GstPushSrc * src, + GstBuffer ** buffer); #define gst_tensor_repopop_parent_class parent_class G_DEFINE_TYPE (GstTensorRepoPop, gst_tensor_repopop, GST_TYPE_PUSH_SRC); +/** + * @brief class initialization of tensor_repopop + */ static void gst_tensor_repopop_class_init (GstTensorRepoPopClass * klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (kalss); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); - GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (kalss); + GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass); gobject_class->set_property = gst_tensor_repopop_set_property; gobject_class->get_property = gst_tensor_repopop_get_property; @@ -103,12 +112,14 @@ gst_tensor_repopop_class_init (GstTensorRepoPopClass * klass) g_param_spec_boolean ("silent", "Silent", "Produce verbose output", DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SLOT_ID, + g_param_spec_uint ("slot-index", "Slot Index", "repository slot index", + 0, UINT_MAX, DEFAULT_INDEX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gobject_class->dispose = gst_tensor_repopop_dispose; basesrc_class->get_caps = gst_tensor_repopop_getcaps; - basesrc_class->query = gst_tensor_repopop_query; - pushsrc_class->create = gst_tensor_repopop_create; gst_element_class_set_static_metadata (element_class, @@ -120,37 +131,175 @@ gst_tensor_repopop_class_init (GstTensorRepoPopClass * klass) gst_element_class_add_static_pad_template (element_class, &src_template); } +/** + * @brief object initialization of tensor_repopop + */ static void gst_tensor_repopop_init (GstTensorRepoPop * self) { self->silent = TRUE; - + self->ini = FALSE; + gst_tensors_config_init (&self->config); + self->caps = NULL; } +/** + * @brief object dispose of tensor_repopop + */ +static void +gst_tensor_repopop_dispose (GObject * object) +{ + gboolean ret; + GstTensorRepoPop *self = GST_TENSOR_REPOPOP (object); + 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); + if (self->caps) + gst_caps_unref (self->caps); + G_OBJECT_CLASS (parent_class)->dispose (object); +} +/** + * @brief get cap of tensor_repopop + */ +static GstCaps * +gst_tensor_repopop_getcaps (GstBaseSrc * src, GstCaps * filter) +{ + GstCaps *cap; + GstTensorRepoPop *self = GST_TENSOR_REPOPOP (src); + + GST_DEBUG_OBJECT (self, "returning %" GST_PTR_FORMAT, self->caps); + + if (self->caps) { + if (filter) { + cap = + gst_caps_intersect_full (filter, self->caps, + GST_CAPS_INTERSECT_FIRST); + } else + cap = gst_caps_ref (self->caps); + } else { + if (filter) { + cap = gst_caps_ref (filter); + } else + cap = gst_caps_new_any (); + } + + return cap; +} +/** + * @brief set property of tensor_repopop + */ +static void +gst_tensor_repopop_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTensorRepoPop *self = GST_TENSOR_REPOPOP (object); + + switch (prop_id) { + case PROP_SILENT: + self->silent = g_value_get_boolean (value); + break; + case PROP_SLOT_ID: + self->myid = g_value_get_uint (value); + break; + case PROP_CAPS: + { + GstStructure *st = NULL; + const GstCaps *caps = gst_value_get_caps (value); + GstCaps *new_caps; + + if (caps == NULL) { + new_caps = gst_caps_new_any (); + } else { + new_caps = gst_caps_copy (caps); + } + gst_caps_replace (&self->caps, new_caps); + gst_pad_set_caps (GST_BASE_SRC_PAD (self), new_caps); + st = gst_caps_get_structure (new_caps, 0); + + gst_tensors_config_from_structure (&self->config, st); + + if (new_caps && gst_caps_get_size (new_caps) == 1 && st + && gst_structure_get_fraction (st, "framerate", &self->fps_n, + &self->fps_d)) { + GST_INFO_OBJECT (self, "Seting framerate to %d/%d", self->fps_n, + self->fps_d); + } else { + self->fps_n = -1; + self->fps_d = -1; + } + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} +/** + * @brief get property of tensor_repopop + */ +static void +gst_tensor_repopop_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTensorRepoPop *self = GST_TENSOR_REPOPOP (object); + + switch (prop_id) { + case PROP_SILENT: + g_value_set_boolean (value, self->silent); + break; + case PROP_SLOT_ID: + g_value_set_uint (value, self->myid); + break; + case PROP_CAPS: + gst_value_set_caps (value, self->caps); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} +/** + * @brief create func of tensor_repopop + */ +static GstFlowReturn +gst_tensor_repopop_create (GstPushSrc * src, GstBuffer ** buffer) +{ + GstTensorRepoPop *self; + GstBuffer *buf; + self = GST_TENSOR_REPOPOP (src); + gst_tensor_repo_wait (); + if (gst_tensor_repo_check_eos (self->myid)) + return GST_FLOW_EOS; + if (!self->ini) { + int i; + guint num_tensors = self->config.info.num_tensors; + gsize size = 0; + for (i = 0; i < num_tensors; i++) + size += gst_tensor_info_get_size (&self->config.info.info[i]); + buf = gst_buffer_new_and_alloc (size); + gst_buffer_memset (buf, 0, 0, size); + self->ini = TRUE; + } else { + buf = gst_tensor_repopop_buffer (self->myid); + } + *buffer = buf; - - - - - - - - - - + return GST_FLOW_OK; +} /** * @brief Function to initialize the plugin. @@ -165,27 +314,3 @@ NNSTREAMER_PLUGIN_INIT (tensor_repopop) return gst_element_register (plugin, "tensor_repopop", GST_RANK_NONE, GST_TYPE_TENSOR_REPOPOP); } - -#ifndef SINGLE_BINARY -/** - * @brief Definition for identifying tensor_repopop 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_repopop, - "Pop element to handle tensor repository", - gst_tensor_repopop_plugin_init, VERSION, "LGPL", "nnstreamer", - "https://github.com/nnsuite/nnstreamer"); -#endif diff --git a/gst/tensor_repopop/tensor_repopop.h b/gst/tensor_repopop/tensor_repopop.h index 7d4960f..8464428 100644 --- a/gst/tensor_repopop/tensor_repopop.h +++ b/gst/tensor_repopop/tensor_repopop.h @@ -52,12 +52,14 @@ typedef struct _GstTensorRepoPopClass GstTensorRepoPopClass; */ struct _GstTensorRepoPop { + GstPushSrc parent; GstBaseSink element; - + GstTensorsConfig config; gboolean silent; - GstCaps *caps; - GstTensorData data; guint myid; + GstCaps *caps; + gboolean ini; + gint fps_n, fps_d; }; /** @@ -67,7 +69,7 @@ struct _GstTensorRepoPop */ struct _GstTensorRepoPopClass { - GstBaseSinkClass parent_class; + GstPushSrcClass parent_class; }; /** diff --git a/gst/tensor_repopush/tensor_repopush.c b/gst/tensor_repopush/tensor_repopush.c index eabf796..0a2748e 100644 --- a/gst/tensor_repopush/tensor_repopush.c +++ b/gst/tensor_repopush/tensor_repopush.c @@ -75,6 +75,8 @@ static void gst_tensor_repopush_dispose (GObject * object); static gboolean gst_tensor_repopush_start (GstBaseSink * sink); static gboolean gst_tensor_repopush_stop (GstBaseSink * sink); +static gboolean gst_tensor_repopush_event (GstBaseSink * sink, + GstEvent * event); static gboolean gst_tensor_repopush_query (GstBaseSink * sink, GstQuery * query); static GstFlowReturn gst_tensor_repopush_render (GstBaseSink * sink, @@ -131,6 +133,7 @@ gst_tensor_repopush_class_init (GstTensorRepoPushClass * klass) basesink_class->start = GST_DEBUG_FUNCPTR (gst_tensor_repopush_start); basesink_class->stop = GST_DEBUG_FUNCPTR (gst_tensor_repopush_stop); + basesink_class->event = GST_DEBUG_FUNCPTR (gst_tensor_repopush_event); basesink_class->query = GST_DEBUG_FUNCPTR (gst_tensor_repopush_query); basesink_class->render = GST_DEBUG_FUNCPTR (gst_tensor_repopush_render); basesink_class->render_list = @@ -145,23 +148,12 @@ 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); - self->data.config = NULL; - self->data.buffer = NULL; + gst_tensor_repo_init (); - g_mutex_init (&self->data.lock); - g_cond_init (&self->data.cond); - - ret = gst_tensor_repo_add_data (&self->data, self->myid); - g_assert (ret); - -<<<<<<< HEAD -======= - silent_debug ("GstTensorData is sucessfully added : key[%d]", self->myid); ->>>>>>> [Repo/Push] Use Has Table to handle repo & add slot_id property + silent_debug ("GstTensorRepo is sucessfully initailzed"); self->silent = DEFAULT_SILENT; self->signal_rate = DEFAULT_SIGNAL_RATE; @@ -190,6 +182,7 @@ gst_tensor_repopush_set_property (GObject * object, guint prop_id, break; case PROP_SLOT: self->myid = g_value_get_uint (value); + gst_tensor_repo_add_data (self->myid); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -228,13 +221,12 @@ 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); - 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); + if (self->in_caps) + gst_caps_unref (self->in_caps); + + G_OBJECT_CLASS (parent_class)->dispose (object); } /** @@ -256,6 +248,34 @@ gst_tensor_repopush_stop (GstBaseSink * sink) } /** + * @brief Handle events. + * + * GstBaseSink method implementation. + */ +static gboolean +gst_tensor_repopush_event (GstBaseSink * sink, GstEvent * event) +{ + GstTensorRepoPush *self; + GstEventType type; + + self = GST_TENSOR_REPOPUSH (sink); + type = GST_EVENT_TYPE (event); + + silent_debug ("received event %s", GST_EVENT_TYPE_NAME (event)); + + switch (type) { + case GST_EVENT_EOS: + gst_tensor_repo_set_eos (self->myid); + break; + + default: + break; + } + + return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); +} + +/** * @brief query vmethod implementation */ static gboolean @@ -330,6 +350,7 @@ gst_tensor_repopush_render (GstBaseSink * sink, GstBuffer * buffer) GstTensorRepoPush *self; self = GST_TENSOR_REPOPUSH (sink); + gst_tensor_repopush_render_buffer (self, buffer); return GST_FLOW_OK; } @@ -366,10 +387,7 @@ gst_tensor_repopush_set_caps (GstBaseSink * sink, GstCaps * caps) GstTensorRepoPush *self; self = GST_TENSOR_REPOPUSH (sink); - - GST_TENSOR_REPO_LOCK (self->myid); gst_caps_replace (&self->in_caps, caps); - GST_TENSOR_REPO_UNLOCK (self->myid); return TRUE; } @@ -385,7 +403,6 @@ gst_tensor_repopush_get_caps (GstBaseSink * sink, GstCaps * filter) self = GST_TENSOR_REPOPUSH (sink); - GST_TENSOR_REPO_LOCK (self->myid); caps = self->in_caps; if (caps) { @@ -395,7 +412,6 @@ gst_tensor_repopush_get_caps (GstBaseSink * sink, GstCaps * filter) gst_caps_ref (caps); } } - GST_TENSOR_REPO_UNLOCK (self->myid); return caps; } diff --git a/gst/tensor_repopush/tensor_repopush.h b/gst/tensor_repopush/tensor_repopush.h index b688220..cb2a4a9 100644 --- a/gst/tensor_repopush/tensor_repopush.h +++ b/gst/tensor_repopush/tensor_repopush.h @@ -59,10 +59,7 @@ struct _GstTensorRepoPush guint signal_rate; GstClockTime last_render_time; GstCaps *in_caps; - GstTensorData data; guint myid; - guint slot_index; - }; /**