*/
/**
- * SECTION: element-tensor_reposink
+ * SECTION: element-tensor_repopush
*
- * Sink elemnt to handle tensor repo
+ * Push elemnt to handle tensor repo
*
- * @file tensor_reposink.c
+ * @file tensor_repopush.c
* @date 19 Nov 2018
* @brief GStreamer plugin to handle tensor repository
* @see https://github.com/nnsuite/nnstreamer
#include <config.h>
#endif
-#include "tensor_reposink.h"
+#include "tensor_repopush.h"
/**
* @brief Macro for debug mode.
#endif
/**
- * @brief Macro for debug message.
- */
-#define silent_debug(...) \
- debug_print (DBG, __VA_ARGS__)
-
-GST_DEBUG_CATEGORY_STATIC (gst_tensor_reposink_debug);
-#define GST_CAT_DEFAULT gst_tensor_reposink_debug
-
-/**
* @brief tensor repository
*/
-GstTensorRepo _repo;
+extern GstTensorRepo _repo;
/**
- * @brief tensor_reposink signals
+ * @brief Macro for debug message.
*/
-enum
-{
- SIGNAL_NEW_DATA,
- SIGNAL_STREAM_START,
- SIGNAL_EOS,
- LAST_SIGNAL
-};
+#define silent_debug(...) \
+ debug_print (DBG, __VA_ARGS__)
+
+GST_DEBUG_CATEGORY_STATIC (gst_tensor_repopush_debug);
+#define GST_CAT_DEFAULT gst_tensor_repopush_debug
/**
- * @brief tensor_reposink properties
+ * @brief tensor_repopush properties
*/
enum
{
+ PROP_0,
PROP_SIGNAL_RATE,
- PROP_EMIT_SIGNAL,
PROP_SILENT
};
-#define DEFAULT_EMIT_SIGNAL TRUE
#define DEFAULT_SIGNAL_RATE 0
#define DEFAULT_SILENT TRUE
#define DEFAULT_QOS TRUE
/**
- * @brief tensor_reposink sink template
+ * @brief tensor_repopush sink template
*/
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT "; " GST_TENSORS_CAP_DEFAULT));
-static guint _tensor_reposink_signals[LAST_SIGNAL] = { 0 };
-
-static void gst_tensor_reposink_set_property (GObject * object, guint prop_id,
+static void gst_tensor_repopush_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
-static void gst_tensor_reposink_get_property (GObject * object, guint prop_id,
+static void gst_tensor_repopush_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static void gst_tensor_reposink_dispose (GObject * object);
-static void gst_tensor_reposink_finalize (GObject * object);
-
-/** GstBaseSink method implementation */
-static gboolean gst_tensor_reposink_start (GstBaseSink * sink);
-static gboolean gst_tensor_reposink_stop (GstBaseSink * sink);
-static gboolean gst_tensor_reposink_event (GstBaseSink * sink,
- GstEvent * event);
-static gboolean gst_tensor_reposink_query (GstBaseSink * sink,
+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_query (GstBaseSink * sink,
GstQuery * query);
-static GstFlowReturn gst_tensor_reposink_render (GstBaseSink * sink,
+static GstFlowReturn gst_tensor_repopush_render (GstBaseSink * sink,
GstBuffer * buffer);
-static GstFlowReturn gst_tensor_reposink_render_list (GstBaseSink * sink,
+static GstFlowReturn gst_tensor_repopush_render_list (GstBaseSink * sink,
GstBufferList * buffer_list);
-static gboolean gst_tensor_reposink_set_caps (GstBaseSink * sink,
+static gboolean gst_tensor_repopush_set_caps (GstBaseSink * sink,
GstCaps * caps);
-static GstCaps *gst_tensor_reposink_get_caps (GstBaseSink * sink,
+static GstCaps *gst_tensor_repopush_get_caps (GstBaseSink * sink,
GstCaps * filter);
-#define gst_tensor_reposink_parent_class parent_class
-G_DEFINE_TYPE (GstTensorRepoSink, gst_tensor_reposink, GST_TYPE_BASE_SINK);
+#define gst_tensor_repopush_parent_class parent_class
+G_DEFINE_TYPE (GstTensorRepoPush, gst_tensor_repopush, GST_TYPE_BASE_SINK);
/**
- * @brief class initialization of tensor_reposink
+ * @brief class initialization of tensor_repopush
*/
static void
-gst_tensor_reposink_class_init (GstTensorRepoSinkClass * klass)
+gst_tensor_repopush_class_init (GstTensorRepoPushClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *element_class;
element_class = GST_ELEMENT_CLASS (klass);
basesink_class = GST_BASE_SINK_CLASS (klass);
- gobject_class->set_property = gst_tensor_reposink_set_property;
- gobject_class->get_property = gst_tensor_reposink_get_property;
- gobject_class->dispose = gst_tensor_reposink_dispose;
- gobject_class->finalize = gst_tensor_reposink_finalize;
+ gobject_class->set_property = gst_tensor_repopush_set_property;
+ gobject_class->get_property = gst_tensor_repopush_get_property;
+ gobject_class->dispose = gst_tensor_repopush_dispose;
g_object_class_install_property (gobject_class, PROP_SIGNAL_RATE,
g_param_spec_uint ("signal-rate", "Signal rate",
"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_EMIT_SIGNAL,
- g_param_spec_boolean ("emit-signal", "Emit signal",
- "Emit signal for new data, stream start, eos", DEFAULT_EMIT_SIGNAL,
- 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));
- _tensor_reposink_signals[SIGNAL_STREAM_START] =
- g_signal_new ("stream-start", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstTensorRepoSinkClass, stream_start),
- NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
-
- _tensor_reposink_signals[SIGNAL_EOS] =
- g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstTensorRepoSinkClass, eos), NULL, NULL, NULL,
- G_TYPE_NONE, 0, G_TYPE_NONE);
-
gst_element_class_set_static_metadata (element_class,
- "TensorRepoSink",
- "Sink/TensorRepo",
- "Sink element to handle tensor repository",
+ "TensorRepoPush",
+ "Push/TensorRepo",
+ "Push element to handle tensor repository",
"Samsung Electronics Co., Ltd.");
gst_element_class_add_static_pad_template (element_class, &sink_template);
- basesink_class->start = GST_DEBUG_FUNCPTR (gst_tensor_reposink_start);
- basesink_class->stop = GST_DEBUG_FUNCPTR (gst_tensor_reposink_stop);
- basesink_class->event = GST_DEBUG_FUNCPTR (gst_tensor_reposink_event);
- basesink_class->query = GST_DEBUG_FUNCPTR (gst_tensor_reposink_query);
- basesink_class->render = GST_DEBUG_FUNCPTR (gst_tensor_reposink_render);
+ basesink_class->start = GST_DEBUG_FUNCPTR (gst_tensor_repopush_start);
+ basesink_class->stop = GST_DEBUG_FUNCPTR (gst_tensor_repopush_stop);
+ basesink_class->query = GST_DEBUG_FUNCPTR (gst_tensor_repopush_query);
+ basesink_class->render = GST_DEBUG_FUNCPTR (gst_tensor_repopush_render);
basesink_class->render_list =
- GST_DEBUG_FUNCPTR (gst_tensor_reposink_render_list);
- basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_tensor_reposink_set_caps);
- basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_tensor_reposink_get_caps);
+ GST_DEBUG_FUNCPTR (gst_tensor_repopush_render_list);
+ basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_tensor_repopush_set_caps);
+ basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_tensor_repopush_get_caps);
}
/**
- * @brief initialization of tensor_reposink
+ * @brief initialization of tensor_repopush
*/
static void
-gst_tensor_reposink_init (GstTensorRepoSink * self)
+gst_tensor_repopush_init (GstTensorRepoPush * self)
{
GstBaseSink *basesink;
basesink = GST_BASE_SINK (self);
g_mutex_init (&self->data.lock);
g_cond_init (&self->data.cond);
- g_mutex_lock (&_repo.repo_lock);
- _repo.tensorsdata = g_slist_append (_repo.tensorsdata, &self->data);
-
- self->myid = _repo.num_buffer;
- _repo.num_buffer++;
- g_mutex_unlock (&_repo.repo_lock);
+ self->myid = gst_tensor_repo_add_data (&self->data);
self->silent = DEFAULT_SILENT;
- self->emit_signal = DEFAULT_EMIT_SIGNAL;
self->signal_rate = DEFAULT_SIGNAL_RATE;
self->last_render_time = GST_CLOCK_TIME_NONE;
self->in_caps = NULL;
* @brief set property vmethod
*/
static void
-gst_tensor_reposink_set_property (GObject * object, guint prop_id,
+gst_tensor_repopush_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
- /* NYI */
+ GstTensorRepoPush *self;
+ self = GST_TENSOR_REPOPUSH (object);
+
+ switch (prop_id) {
+ case PROP_SIGNAL_RATE:
+ self->signal_rate = g_value_get_uint (value);
+ break;
+ case PROP_SILENT:
+ self->silent = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
/**
* @brief get property vmethod
*/
static void
-gst_tensor_reposink_get_property (GObject * object, guint prop_id,
+gst_tensor_repopush_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
- /* NYI */
+ GstTensorRepoPush *self;
+ self = GST_TENSOR_REPOPUSH (object);
+ switch (prop_id) {
+ case PROP_SIGNAL_RATE:
+ g_value_set_uint (value, self->signal_rate);
+ break;
+ case PROP_SILENT:
+ g_value_set_boolean (value, self->silent);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
/**
* @brief dispose vmethod implementation
*/
static void
-gst_tensor_reposink_dispose (GObject * object)
+gst_tensor_repopush_dispose (GObject * object)
{
- GstTensorRepoSink *self;
- GstTensorData *data;
- self = GST_TENSOR_REPOSINK (object);
-
- GST_TENSOR_REPO_LOCK (self->myid);
- data = gst_tensor_repo_get_tensor (self->myid);
- gst_object_unref (data->config);
- gst_object_unref (data->buffer);
- GST_TENSOR_REPO_UNLOCK (self->myid);
-
- g_mutex_clear (GST_TENSOR_REPO_GET_LOCK (self->myid));
- g_cond_clear (GST_TENSOR_REPO_GET_COND (self->myid));
-
+ GstTensorRepoPush *self;
+ self = GST_TENSOR_REPOPUSH (object);
gst_tensor_repo_remove_data (self->myid);
}
/**
- * @brief finalize vmethod implementation
- */
-static void
-gst_tensor_reposink_finalize (GObject * object)
-{
- GstTensorRepoSink *self;
-
- self = GST_TENSOR_REPOSINK (object);
- g_mutex_clear (GST_TENSOR_REPO_GET_LOCK (self->myid));
- g_cond_clear (GST_TENSOR_REPO_GET_COND (self->myid));
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/**
* @brief start vmethod implementation
*/
static gboolean
-gst_tensor_reposink_start (GstBaseSink * sink)
+gst_tensor_repopush_start (GstBaseSink * sink)
{
return TRUE;
}
* @brief stop vmethod implementation
*/
static gboolean
-gst_tensor_reposink_stop (GstBaseSink * sink)
+gst_tensor_repopush_stop (GstBaseSink * sink)
{
return TRUE;
}
/**
- * @brief event vmethod implementation
- */
-static gboolean
-gst_tensor_reposink_event (GstBaseSink * sink, GstEvent * event)
-{
- GstTensorRepoSink *self;
- GstEventType type;
-
- self = GST_TENSOR_REPOSINK (sink);
- type = GST_EVENT_TYPE (event);
-
- switch (type) {
- case GST_EVENT_STREAM_START:
- break;
-
- case GST_EVENT_EOS:
- break;
-
- default:
- break;
- }
-
- silent_debug ("received event %s", GST_EVENT_TYPE_NAME (event));
-
- return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
-}
-
-/**
* @brief query vmethod implementation
*/
static gboolean
-gst_tensor_reposink_query (GstBaseSink * sink, GstQuery * query)
+gst_tensor_repopush_query (GstBaseSink * sink, GstQuery * query)
{
- GstTensorRepoSink *self;
+ GstTensorRepoPush *self;
GstQueryType type;
GstFormat format;
- self = GST_TENSOR_REPOSINK (sink);
+ self = GST_TENSOR_REPOPUSH (sink);
type = GST_QUERY_TYPE (query);
silent_debug ("received query %s", GST_QUERY_TYPE_NAME (query));
return GST_BASE_SINK_CLASS (parent_class)->query (sink, query);
}
+
+/**
+ * @brief push GstBuffer
+ */
+static void
+gst_tensor_repopush_render_buffer (GstTensorRepoPush * self, GstBuffer * buffer)
+{
+ GstClockTime now = GST_CLOCK_TIME_NONE;
+ guint signal_rate;
+ gboolean notify = FALSE;
+ g_return_if_fail (GST_IS_TENSOR_REPOPUSH (self));
+
+ signal_rate = self->signal_rate;
+
+ if (signal_rate) {
+ GstClock *clock;
+ GstClockTime render_time;
+ clock = gst_element_get_clock (GST_ELEMENT (self));
+
+ if (clock) {
+ now = gst_clock_get_time (clock);
+ render_time = (1000 / signal_rate) * GST_MSECOND + self->last_render_time;
+ if (!GST_CLOCK_TIME_IS_VALID (self->last_render_time) ||
+ GST_CLOCK_DIFF (now, render_time) <= 0)
+ notify = TRUE;
+ gst_object_unref (clock);
+ }
+ } else {
+ notify = TRUE;
+ }
+
+ if (notify) {
+ self->last_render_time = now;
+ gst_tensor_repo_push_buffer (self->myid, buffer);
+ }
+}
+
/**
* @brief render vmethod implementation
*/
static GstFlowReturn
-gst_tensor_reposink_render (GstBaseSink * sink, GstBuffer * buffer)
+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;
}
* @brief render list vmethod implementation
*/
static GstFlowReturn
-gst_tensor_reposink_render_list (GstBaseSink * sink,
+gst_tensor_repopush_render_list (GstBaseSink * sink,
GstBufferList * buffer_list)
{
+ GstTensorRepoPush *self;
+ GstBuffer *buffer;
+ guint i;
+ guint num_buffers;
+
+ self = GST_TENSOR_REPOPUSH (sink);
+ num_buffers = gst_buffer_list_length (buffer_list);
+
+ for (i = 0; i < num_buffers; i++) {
+ buffer = gst_buffer_list_get (buffer_list, i);
+ gst_tensor_repopush_render_buffer (self, buffer);
+ }
+
return GST_FLOW_OK;
}
* @brief set_caps vmethod implementation
*/
static gboolean
-gst_tensor_reposink_set_caps (GstBaseSink * sink, GstCaps * caps)
+gst_tensor_repopush_set_caps (GstBaseSink * sink, GstCaps * caps)
{
- GstTensorRepoSink *self;
+ GstTensorRepoPush *self;
- self = GST_TENSOR_REPOSINK (sink);
+ self = GST_TENSOR_REPOPUSH (sink);
GST_TENSOR_REPO_LOCK (self->myid);
gst_caps_replace (&self->in_caps, caps);
* @brief get_caps vmethod implementation
*/
static GstCaps *
-gst_tensor_reposink_get_caps (GstBaseSink * sink, GstCaps * filter)
+gst_tensor_repopush_get_caps (GstBaseSink * sink, GstCaps * filter)
{
- GstTensorRepoSink *self;
+ GstTensorRepoPush *self;
GstCaps *caps;
- self = GST_TENSOR_REPOSINK (sink);
+ self = GST_TENSOR_REPOPUSH (sink);
GST_TENSOR_REPO_LOCK (self->myid);
caps = self->in_caps;
*
* See GstPluginInitFunc() for more details.
*/
-NNSTREAMER_PLUGIN_INIT (tensor_reposink)
+NNSTREAMER_PLUGIN_INIT (tensor_repopush)
{
- GST_DEBUG_CATEGORY_INIT (gst_tensor_reposink_debug, "tensor_reposink",
- 0, "tensor_reposink element");
+ GST_DEBUG_CATEGORY_INIT (gst_tensor_repopush_debug, "tensor_repopush",
+ 0, "tensor_repopush element");
- return gst_element_register (plugin, "tensor_reposink",
- GST_RANK_NONE, GST_TYPE_TENSOR_REPOSINK);
+ return gst_element_register (plugin, "tensor_repopush",
+ GST_RANK_NONE, GST_TYPE_TENSOR_REPOPUSH);
}
#ifndef SINGLE_BINARY
*/
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
- tensor_reposink,
- "Sink element to handle tensor repository",
- gst_tensor_reposink_plugin_init, VERSION, "LGPL", "nnstreamer",
+ tensor_repopush,
+ "Push element to handle tensor repository",
+ gst_tensor_repopush_plugin_init, VERSION, "LGPL", "nnstreamer",
"https://github.com/nnsuite/nnstreamer");
#endif