Doxygen Book
gsttensor_reposink.c
Go to the documentation of this file.
1 
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 #include <nnstreamer_util.h>
35 
36 #include "gsttensor_repo.h"
37 #include "gsttensor_reposink.h"
38 
39 GST_DEBUG_CATEGORY_STATIC (gst_tensor_reposink_debug);
40 #define GST_CAT_DEFAULT gst_tensor_reposink_debug
41 
45 enum
46 {
51 };
52 
53 #define DEFAULT_SIGNAL_RATE 0
54 #define DEFAULT_SILENT TRUE
55 #define DEFAULT_QOS TRUE
56 #define DEFAULT_INDEX 0
57 
58 static void gst_tensor_reposink_set_property (GObject * object, guint prop_id,
59  const GValue * value, GParamSpec * pspec);
60 static void gst_tensor_reposink_get_property (GObject * object, guint prop_id,
61  GValue * value, GParamSpec * pspec);
62 static void gst_tensor_reposink_dispose (GObject * object);
63 
64 static gboolean gst_tensor_reposink_start (GstBaseSink * sink);
65 static gboolean gst_tensor_reposink_stop (GstBaseSink * sink);
66 static gboolean gst_tensor_reposink_event (GstBaseSink * sink,
67  GstEvent * event);
68 static gboolean gst_tensor_reposink_query (GstBaseSink * sink,
69  GstQuery * query);
70 static GstFlowReturn gst_tensor_reposink_render (GstBaseSink * sink,
71  GstBuffer * buffer);
72 static GstFlowReturn gst_tensor_reposink_render_list (GstBaseSink * sink,
73  GstBufferList * buffer_list);
74 static gboolean gst_tensor_reposink_set_caps (GstBaseSink * sink,
75  GstCaps * caps);
76 static GstCaps *gst_tensor_reposink_get_caps (GstBaseSink * sink,
77  GstCaps * filter);
78 
79 #define gst_tensor_reposink_parent_class parent_class
80 G_DEFINE_TYPE (GstTensorRepoSink, gst_tensor_reposink, GST_TYPE_BASE_SINK);
81 
85 static void
87 {
88  GObjectClass *gobject_class;
89  GstElementClass *element_class;
90  GstBaseSinkClass *basesink_class;
91  GstPadTemplate *pad_template;
92  GstCaps *pad_caps;
93 
94  GST_DEBUG_CATEGORY_INIT (gst_tensor_reposink_debug, "tensor_reposink", 0,
95  "Sink element to handle tensor repository");
96 
97  gobject_class = G_OBJECT_CLASS (klass);
98  element_class = GST_ELEMENT_CLASS (klass);
99  basesink_class = GST_BASE_SINK_CLASS (klass);
100 
101  gobject_class->set_property = gst_tensor_reposink_set_property;
102  gobject_class->get_property = gst_tensor_reposink_get_property;
103  gobject_class->dispose = gst_tensor_reposink_dispose;
104 
105  g_object_class_install_property (gobject_class, PROP_SIGNAL_RATE,
106  g_param_spec_uint ("signal-rate", "Signal rate",
107  "New data signals per second (0 for unlimited, max 500)", 0, 500,
108  DEFAULT_SIGNAL_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
109 
110  g_object_class_install_property (gobject_class, PROP_SLOT,
111  g_param_spec_uint ("slot-index", "Slot Index", "repository slot index",
112  0, UINT_MAX, DEFAULT_INDEX,
113  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
114 
115  g_object_class_install_property (gobject_class, PROP_SILENT,
116  g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
117  DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
118 
119  gst_element_class_set_static_metadata (element_class,
120  "TensorRepoSink",
121  "Sink/Tensor/Repository",
122  "Set element to handle tensor repository",
123  "Samsung Electronics Co., Ltd.");
124 
125  /* pad template */
126  pad_caps = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT "; "
128  pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
129  pad_caps);
130  gst_element_class_add_pad_template (element_class, pad_template);
131  gst_caps_unref (pad_caps);
132 
133  basesink_class->start = GST_DEBUG_FUNCPTR (gst_tensor_reposink_start);
134  basesink_class->stop = GST_DEBUG_FUNCPTR (gst_tensor_reposink_stop);
135  basesink_class->event = GST_DEBUG_FUNCPTR (gst_tensor_reposink_event);
136  basesink_class->query = GST_DEBUG_FUNCPTR (gst_tensor_reposink_query);
137  basesink_class->render = GST_DEBUG_FUNCPTR (gst_tensor_reposink_render);
138  basesink_class->render_list =
139  GST_DEBUG_FUNCPTR (gst_tensor_reposink_render_list);
140  basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_tensor_reposink_set_caps);
141  basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_tensor_reposink_get_caps);
142 }
143 
147 static void
149 {
150  GstBaseSink *basesink;
151 
152  basesink = GST_BASE_SINK (self);
153 
155 
156  GST_DEBUG_OBJECT (self, "GstTensorRepo is successfully initialized");
157 
158  self->silent = DEFAULT_SILENT;
159  self->signal_rate = DEFAULT_SIGNAL_RATE;
160  self->last_render_time = GST_CLOCK_TIME_NONE;
161  self->set_startid = FALSE;
162  self->in_caps = NULL;
163 
164  gst_base_sink_set_qos_enabled (basesink, DEFAULT_QOS);
165 
166  /* ignore sync and preroll in repo */
167  gst_base_sink_set_sync (basesink, FALSE);
168  gst_base_sink_set_async_enabled (basesink, FALSE);
169 }
170 
174 static void
175 gst_tensor_reposink_set_property (GObject * object, guint prop_id,
176  const GValue * value, GParamSpec * pspec)
177 {
178  GstTensorRepoSink *self;
179 
180  self = GST_TENSOR_REPOSINK (object);
181 
182  switch (prop_id) {
183  case PROP_SIGNAL_RATE:
184  self->signal_rate = g_value_get_uint (value);
185  break;
186  case PROP_SILENT:
187  self->silent = g_value_get_boolean (value);
188  break;
189  case PROP_SLOT:
190  self->o_myid = self->myid;
191  self->myid = g_value_get_uint (value);
192 
193  gst_tensor_repo_add_repodata (self->myid, TRUE);
194 
195  if (!self->set_startid) {
196  self->o_myid = self->myid;
197  self->set_startid = TRUE;
198  }
199 
200  if (self->o_myid != self->myid)
201  gst_tensor_repo_set_changed (self->o_myid, self->myid, TRUE);
202  break;
203  default:
204  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
205  break;
206  }
207 }
208 
212 static void
213 gst_tensor_reposink_get_property (GObject * object, guint prop_id,
214  GValue * value, GParamSpec * pspec)
215 {
216  GstTensorRepoSink *self;
217 
218  self = GST_TENSOR_REPOSINK (object);
219 
220  switch (prop_id) {
221  case PROP_SIGNAL_RATE:
222  g_value_set_uint (value, self->signal_rate);
223  break;
224  case PROP_SILENT:
225  g_value_set_boolean (value, self->silent);
226  break;
227  case PROP_SLOT:
228  g_value_set_uint (value, self->myid);
229  break;
230  default:
231  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
232  break;
233  }
234 }
235 
239 static void
240 gst_tensor_reposink_dispose (GObject * object)
241 {
242  GstTensorRepoSink *self;
243 
244  self = GST_TENSOR_REPOSINK (object);
245 
246  if (self->in_caps)
247  gst_caps_unref (self->in_caps);
248 
249  G_OBJECT_CLASS (parent_class)->dispose (object);
250 }
251 
255 static gboolean
256 gst_tensor_reposink_start (GstBaseSink * sink)
257 {
258  UNUSED (sink);
259  return TRUE;
260 }
261 
265 static gboolean
266 gst_tensor_reposink_stop (GstBaseSink * sink)
267 {
268  UNUSED (sink);
269  return TRUE;
270 }
271 
277 static gboolean
278 gst_tensor_reposink_event (GstBaseSink * sink, GstEvent * event)
279 {
280  GstTensorRepoSink *self;
281  GstEventType type;
282 
283  self = GST_TENSOR_REPOSINK (sink);
284  type = GST_EVENT_TYPE (event);
285 
286  GST_DEBUG_OBJECT (self, "received event %s", GST_EVENT_TYPE_NAME (event));
287 
288  switch (type) {
289  case GST_EVENT_EOS:
290  gst_tensor_repo_set_eos (self->myid);
291  break;
292  default:
293  break;
294  }
295 
296  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
297 }
298 
302 static gboolean
303 gst_tensor_reposink_query (GstBaseSink * sink, GstQuery * query)
304 {
305  GstTensorRepoSink *self;
306  GstQueryType type;
307  GstFormat format;
308 
309  self = GST_TENSOR_REPOSINK (sink);
310  type = GST_QUERY_TYPE (query);
311 
312  GST_DEBUG_OBJECT (self, "received query %s", GST_QUERY_TYPE_NAME (query));
313 
314  switch (type) {
315  case GST_QUERY_SEEKING:
316  gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
317  gst_query_set_seeking (query, format, FALSE, 0, -1);
318  return TRUE;
319  default:
320  break;
321  }
322 
323  return GST_BASE_SINK_CLASS (parent_class)->query (sink, query);
324 }
325 
329 static gboolean
331 {
332  GstClockTime now = GST_CLOCK_TIME_NONE;
333  guint signal_rate;
334  gboolean notify = FALSE;
335  g_return_val_if_fail (GST_IS_TENSOR_REPOSINK (self), FALSE);
336 
337  signal_rate = self->signal_rate;
338 
339  if (signal_rate) {
340  GstClock *clock;
341  GstClockTime render_time;
342 
343  clock = gst_element_get_clock (GST_ELEMENT (self));
344 
345  if (clock) {
346  now = gst_clock_get_time (clock);
347  render_time = (1000 / signal_rate) * GST_MSECOND + self->last_render_time;
348 
349  if (!GST_CLOCK_TIME_IS_VALID (self->last_render_time) ||
350  GST_CLOCK_DIFF (now, render_time) <= 0) {
351  notify = TRUE;
352  }
353 
354  gst_object_unref (clock);
355  }
356  } else {
357  notify = TRUE;
358  }
359 
360  if (notify) {
361  self->last_render_time = now;
362 
363  if (!gst_tensor_repo_set_buffer (self->myid, buffer, self->in_caps)) {
364  GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
365  ("Cannot Set buffer into repo [key: %d]", self->myid), NULL);
366  return FALSE;
367  }
368  }
369 
370  return TRUE;
371 }
372 
376 static GstFlowReturn
377 gst_tensor_reposink_render (GstBaseSink * sink, GstBuffer * buffer)
378 {
379  GstTensorRepoSink *self;
380 
381  self = GST_TENSOR_REPOSINK (sink);
382 
383  if (!gst_tensor_reposink_render_buffer (self, buffer))
384  return GST_FLOW_ERROR;
385  return GST_FLOW_OK;
386 }
387 
391 static GstFlowReturn
393  GstBufferList * buffer_list)
394 {
395  GstTensorRepoSink *self;
396  GstBuffer *buffer;
397  guint i;
398  guint num_buffers;
399 
400  self = GST_TENSOR_REPOSINK (sink);
401  num_buffers = gst_buffer_list_length (buffer_list);
402 
403  for (i = 0; i < num_buffers; i++) {
404  buffer = gst_buffer_list_get (buffer_list, i);
405  if (!gst_tensor_reposink_render_buffer (self, buffer))
406  return GST_FLOW_ERROR;
407  }
408 
409  return GST_FLOW_OK;
410 }
411 
415 static gboolean
416 gst_tensor_reposink_set_caps (GstBaseSink * sink, GstCaps * caps)
417 {
418  GstTensorRepoSink *self;
419 
420  self = GST_TENSOR_REPOSINK (sink);
421  gst_caps_replace (&self->in_caps, caps);
422 
423  /* debug print caps */
424  if (!self->silent) {
425  GstStructure *structure;
426  gchar *str;
427  guint caps_size, i;
428 
429  caps_size = gst_caps_get_size (caps);
430  GST_DEBUG_OBJECT (self, "set caps, size is %d", caps_size);
431 
432  for (i = 0; i < caps_size; i++) {
433  structure = gst_caps_get_structure (caps, i);
434  str = gst_structure_to_string (structure);
435 
436  GST_DEBUG_OBJECT (self, "[%d] %s", i, str);
437  g_free (str);
438  }
439  }
440 
441  return TRUE;
442 }
443 
447 static GstCaps *
448 gst_tensor_reposink_get_caps (GstBaseSink * sink, GstCaps * filter)
449 {
450  GstTensorRepoSink *self;
451  GstCaps *caps;
452 
453  self = GST_TENSOR_REPOSINK (sink);
454 
455  caps = self->in_caps;
456 
457  if (caps) {
458  if (filter) {
459  caps = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
460  } else {
461  gst_caps_ref (caps);
462  }
463  }
464 
465  return caps;
466 }
gst_tensor_reposink_init
static void gst_tensor_reposink_init(GstTensorRepoSink *self)
initialization of tensor_reposink
Definition: gsttensor_reposink.c:148
GST_TENSOR_CAP_DEFAULT
#define GST_TENSOR_CAP_DEFAULT
Default static capability for other/tensor.
Definition: tensor_typedef.h:78
gst_tensor_reposink_set_property
static void gst_tensor_reposink_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
set property vmethod
Definition: gsttensor_reposink.c:175
DEFAULT_SILENT
#define DEFAULT_SILENT
Definition: gsttensor_reposink.c:54
FALSE
return FALSE
Definition: gsttensor_transform.c:590
gst_tensor_repo_set_changed
gboolean gst_tensor_repo_set_changed(guint o_nth, guint nth, gboolean is_sink)
Set the changing status of repo.
Definition: gsttensor_repo.c:91
gst_tensor_reposink_dispose
static void gst_tensor_reposink_dispose(GObject *object)
dispose vmethod implementation
Definition: gsttensor_reposink.c:240
gst_tensor_reposink_render
static GstFlowReturn gst_tensor_reposink_render(GstBaseSink *sink, GstBuffer *buffer)
render vmethod implementation
Definition: gsttensor_reposink.c:377
DEFAULT_SIGNAL_RATE
#define DEFAULT_SIGNAL_RATE
Definition: gsttensor_reposink.c:53
gst_tensor_reposink_render_list
static GstFlowReturn gst_tensor_reposink_render_list(GstBaseSink *sink, GstBufferList *buffer_list)
render list vmethod implementation
Definition: gsttensor_reposink.c:392
gst_tensor_reposink_event
static gboolean gst_tensor_reposink_event(GstBaseSink *sink, GstEvent *event)
Handle events.
Definition: gsttensor_reposink.c:278
gst_tensor_reposink_class_init
static void gst_tensor_reposink_class_init(GstTensorRepoSinkClass *klass)
class initialization of tensor_reposink
Definition: gsttensor_reposink.c:86
_GstTensorRepoSink
GstTensorRepoSink data structure.
Definition: gsttensor_reposink.h:54
DEFAULT_QOS
#define DEFAULT_QOS
Definition: gsttensor_reposink.c:55
g_free
g_free(self->option[(opnum) - 1])
opnum: \
GST_IS_TENSOR_REPOSINK
#define GST_IS_TENSOR_REPOSINK(obj)
Definition: gsttensor_reposink.h:41
gst_tensor_repo_set_eos
gboolean gst_tensor_repo_set_eos(guint nth)
Set EOS (End-of-Stream) of slot.
Definition: gsttensor_repo.c:287
PROP_SLOT
@ PROP_SLOT
Definition: gsttensor_reposink.c:49
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorRepoSink, gst_tensor_reposink, GST_TYPE_BASE_SINK)
PROP_SIGNAL_RATE
@ PROP_SIGNAL_RATE
Definition: gsttensor_reposink.c:48
TRUE
return TRUE
Definition: gsttensor_if.c:897
UNUSED
#define UNUSED(expr)
Definition: mqttcommon.h:19
PROP_0
@ PROP_0
Definition: gsttensor_reposink.c:47
gst_tensor_reposink_set_caps
static gboolean gst_tensor_reposink_set_caps(GstBaseSink *sink, GstCaps *caps)
set_caps vmethod implementation
Definition: gsttensor_reposink.c:416
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_reposink.c:50
gst_tensor_reposink_stop
static gboolean gst_tensor_reposink_stop(GstBaseSink *sink)
stop vmethod implementation
Definition: gsttensor_reposink.c:266
nnstreamer_util.h
Optional NNStreamer utility functions for sub-plugin writers and users.
GST_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensor_reposink_debug)
gst_tensor_reposink_render_buffer
static gboolean gst_tensor_reposink_render_buffer(GstTensorRepoSink *self, GstBuffer *buffer)
Push GstBuffer.
Definition: gsttensor_reposink.c:330
GST_TENSORS_CAP_DEFAULT
#define GST_TENSORS_CAP_DEFAULT
Caps string for the caps template of static tensor stream.
Definition: tensor_typedef.h:115
gsttensor_reposink.h
GStreamer plugin to handle tensor repository.
gst_tensor_reposink_get_property
static void gst_tensor_reposink_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
get property vmethod
Definition: gsttensor_reposink.c:213
DEFAULT_INDEX
#define DEFAULT_INDEX
Definition: gsttensor_reposink.c:56
gst_tensor_reposink_get_caps
static GstCaps * gst_tensor_reposink_get_caps(GstBaseSink *sink, GstCaps *filter)
get_caps vmethod implementation
Definition: gsttensor_reposink.c:448
gsttensor_repo.h
tensor repo header file for NNStreamer, the GStreamer plugin for neural networks
gst_tensor_repo_set_buffer
gboolean gst_tensor_repo_set_buffer(guint nth, GstBuffer *buffer, GstCaps *caps)
Push GstBuffer into repo.
Definition: gsttensor_repo.c:193
gst_tensor_reposink_start
static gboolean gst_tensor_reposink_start(GstBaseSink *sink)
start vmethod implementation
Definition: gsttensor_reposink.c:256
_GstTensorRepoSinkClass
GstTensorRepoSinkClass data structure.
Definition: gsttensor_reposink.h:72
gst_tensor_reposink_query
static gboolean gst_tensor_reposink_query(GstBaseSink *sink, GstQuery *query)
query vmethod implementation
Definition: gsttensor_reposink.c:303
type
svtc_1 type
Definition: gsttensor_if.c:843
if
if(!gst_tensordec_process_plugin_options(self,(opnum) - 1)) GST_ERROR_OBJECT(self
gst_tensor_repo_add_repodata
gboolean gst_tensor_repo_add_repodata(guint nth, gboolean is_sink)
Add GstTensorRepoData into repo.
Definition: gsttensor_repo.c:129
GST_TENSOR_REPOSINK
#define GST_TENSOR_REPOSINK(obj)
Definition: gsttensor_reposink.h:37
gst_tensor_repo_init
void gst_tensor_repo_init(void)
GstTensorRepo initialization.
Definition: gsttensor_repo.c:386