Doxygen Book
gsttensor_sink.c
Go to the documentation of this file.
1 
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 
35 #include "gsttensor_sink.h"
36 
40 #ifndef DBG
41 #define DBG (!self->silent)
42 #endif
43 
44 #define silent_debug_timestamp(self, buf) do { \
45  if (DBG) { \
46  GST_DEBUG_OBJECT (self, "pts = %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); \
47  GST_DEBUG_OBJECT (self, "dts = %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_DTS (buf))); \
48  GST_DEBUG_OBJECT (self, "duration = %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); \
49  } \
50 } while (0)
51 
52 GST_DEBUG_CATEGORY_STATIC (gst_tensor_sink_debug);
53 #define GST_CAT_DEFAULT gst_tensor_sink_debug
54 
58 enum
59 {
64 };
65 
69 enum
70 {
75 };
76 
80 #define DEFAULT_EMIT_SIGNAL TRUE
81 
85 #define DEFAULT_SIGNAL_RATE 0
86 
90 #define DEFAULT_SILENT TRUE
91 
97 #define DEFAULT_QOS TRUE
98 
104 #define DEFAULT_SYNC FALSE
105 
109 static guint _tensor_sink_signals[LAST_SIGNAL] = { 0 };
110 
112 static void gst_tensor_sink_set_property (GObject * object, guint prop_id,
113  const GValue * value, GParamSpec * pspec);
114 static void gst_tensor_sink_get_property (GObject * object, guint prop_id,
115  GValue * value, GParamSpec * pspec);
116 static void gst_tensor_sink_finalize (GObject * object);
117 
119 static gboolean gst_tensor_sink_event (GstBaseSink * sink, GstEvent * event);
120 static gboolean gst_tensor_sink_query (GstBaseSink * sink, GstQuery * query);
121 static GstFlowReturn gst_tensor_sink_render (GstBaseSink * sink,
122  GstBuffer * buffer);
123 static GstFlowReturn gst_tensor_sink_render_list (GstBaseSink * sink,
124  GstBufferList * buffer_list);
125 
127 static void gst_tensor_sink_render_buffer (GstTensorSink * self,
128  GstBuffer * buffer);
130  GstClockTime now);
131 static GstClockTime gst_tensor_sink_get_last_render_time (GstTensorSink * self);
132 static void gst_tensor_sink_set_signal_rate (GstTensorSink * self, guint rate);
133 static guint gst_tensor_sink_get_signal_rate (GstTensorSink * self);
135  gboolean emit);
136 static gboolean gst_tensor_sink_get_emit_signal (GstTensorSink * self);
137 static void gst_tensor_sink_set_silent (GstTensorSink * self, gboolean silent);
138 static gboolean gst_tensor_sink_get_silent (GstTensorSink * self);
139 
140 #define gst_tensor_sink_parent_class parent_class
141 G_DEFINE_TYPE (GstTensorSink, gst_tensor_sink, GST_TYPE_BASE_SINK);
142 
146 static void
148 {
149  GObjectClass *gobject_class;
150  GstElementClass *element_class;
151  GstBaseSinkClass *bsink_class;
152  GstPadTemplate *pad_template;
153  GstCaps *pad_caps;
154 
155  GST_DEBUG_CATEGORY_INIT (gst_tensor_sink_debug, "tensor_sink", 0,
156  "Sink element to handle tensor stream");
157 
158  gobject_class = G_OBJECT_CLASS (klass);
159  element_class = GST_ELEMENT_CLASS (klass);
160  bsink_class = GST_BASE_SINK_CLASS (klass);
161 
163  gobject_class->set_property = gst_tensor_sink_set_property;
164  gobject_class->get_property = gst_tensor_sink_get_property;
165  gobject_class->finalize = gst_tensor_sink_finalize;
166 
177  g_object_class_install_property (gobject_class, PROP_SIGNAL_RATE,
178  g_param_spec_uint ("signal-rate", "Signal rate",
179  "New data signals per second (0 for unlimited, max 500)", 0, 500,
180  DEFAULT_SIGNAL_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
181 
187  g_object_class_install_property (gobject_class, PROP_EMIT_SIGNAL,
188  g_param_spec_boolean ("emit-signal", "Emit signal",
189  "Emit signal for new data, stream start, eos", DEFAULT_EMIT_SIGNAL,
190  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
191 
197  g_object_class_install_property (gobject_class, PROP_SILENT,
198  g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
199  DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
200 
207  g_signal_new ("new-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
208  G_STRUCT_OFFSET (GstTensorSinkClass, new_data), NULL, NULL, NULL,
209  G_TYPE_NONE, 1, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
210 
218  g_signal_new ("stream-start", G_TYPE_FROM_CLASS (klass),
219  G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstTensorSinkClass, stream_start),
220  NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
221 
229  g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
230  G_STRUCT_OFFSET (GstTensorSinkClass, eos), NULL, NULL, NULL,
231  G_TYPE_NONE, 0, G_TYPE_NONE);
232 
233  gst_element_class_set_static_metadata (element_class,
234  "TensorSink",
235  "Sink/Tensor",
236  "Sink element to handle tensor stream", "Samsung Electronics Co., Ltd.");
237 
239  pad_caps = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT ";"
240  GST_TENSORS_CAP_MAKE ("{ static, flexible, sparse }"));
241  pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
242  pad_caps);
243  gst_element_class_add_pad_template (element_class, pad_template);
244  gst_caps_unref (pad_caps);
245 
247  bsink_class->event = GST_DEBUG_FUNCPTR (gst_tensor_sink_event);
248  bsink_class->query = GST_DEBUG_FUNCPTR (gst_tensor_sink_query);
249  bsink_class->render = GST_DEBUG_FUNCPTR (gst_tensor_sink_render);
250  bsink_class->render_list = GST_DEBUG_FUNCPTR (gst_tensor_sink_render_list);
251 }
252 
256 static void
258 {
259  GstBaseSink *bsink;
260 
261  bsink = GST_BASE_SINK (self);
262 
263  g_mutex_init (&self->mutex);
264 
266  self->silent = DEFAULT_SILENT;
267  self->emit_signal = DEFAULT_EMIT_SIGNAL;
268  self->signal_rate = DEFAULT_SIGNAL_RATE;
269  self->last_render_time = GST_CLOCK_TIME_NONE;
270 
272  gst_base_sink_set_qos_enabled (bsink, DEFAULT_QOS);
273 
274  /* set 'sync' to synchronize on the clock or not */
275  gst_base_sink_set_sync (bsink, DEFAULT_SYNC);
276 }
277 
283 static void
284 gst_tensor_sink_set_property (GObject * object, guint prop_id,
285  const GValue * value, GParamSpec * pspec)
286 {
287  GstTensorSink *self;
288 
289  self = GST_TENSOR_SINK (object);
290 
291  switch (prop_id) {
292  case PROP_SIGNAL_RATE:
293  gst_tensor_sink_set_signal_rate (self, g_value_get_uint (value));
294  break;
295 
296  case PROP_EMIT_SIGNAL:
297  gst_tensor_sink_set_emit_signal (self, g_value_get_boolean (value));
298  break;
299 
300  case PROP_SILENT:
301  gst_tensor_sink_set_silent (self, g_value_get_boolean (value));
302  break;
303 
304  default:
305  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
306  break;
307  }
308 }
309 
315 static void
316 gst_tensor_sink_get_property (GObject * object, guint prop_id,
317  GValue * value, GParamSpec * pspec)
318 {
319  GstTensorSink *self;
320 
321  self = GST_TENSOR_SINK (object);
322 
323  switch (prop_id) {
324  case PROP_SIGNAL_RATE:
325  g_value_set_uint (value, gst_tensor_sink_get_signal_rate (self));
326  break;
327 
328  case PROP_EMIT_SIGNAL:
329  g_value_set_boolean (value, gst_tensor_sink_get_emit_signal (self));
330  break;
331 
332  case PROP_SILENT:
333  g_value_set_boolean (value, gst_tensor_sink_get_silent (self));
334  break;
335 
336  default:
337  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
338  break;
339  }
340 }
341 
347 static void
348 gst_tensor_sink_finalize (GObject * object)
349 {
350  GstTensorSink *self;
351 
352  self = GST_TENSOR_SINK (object);
353 
354  g_mutex_clear (&self->mutex);
355 
356  G_OBJECT_CLASS (parent_class)->finalize (object);
357 }
358 
364 static gboolean
365 gst_tensor_sink_event (GstBaseSink * sink, GstEvent * event)
366 {
367  GstTensorSink *self;
368  GstEventType type;
369 
370  self = GST_TENSOR_SINK (sink);
371  type = GST_EVENT_TYPE (event);
372 
373  GST_DEBUG_OBJECT (self, "Received %s event: %" GST_PTR_FORMAT,
374  GST_EVENT_TYPE_NAME (event), event);
375 
376  switch (type) {
377  case GST_EVENT_STREAM_START:
378  if (gst_tensor_sink_get_emit_signal (self)) {
379  silent_debug (self, "Emit signal for stream start");
380 
381  g_signal_emit (self, _tensor_sink_signals[SIGNAL_STREAM_START], 0);
382  }
383  break;
384 
385  case GST_EVENT_EOS:
386  if (gst_tensor_sink_get_emit_signal (self)) {
387  silent_debug (self, "Emit signal for eos");
388 
389  g_signal_emit (self, _tensor_sink_signals[SIGNAL_EOS], 0);
390  }
391  break;
392 
393  default:
394  break;
395  }
396 
397  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
398 }
399 
405 static gboolean
406 gst_tensor_sink_query (GstBaseSink * sink, GstQuery * query)
407 {
408  GstTensorSink *self;
409  GstQueryType type;
410  GstFormat format;
411 
412  self = GST_TENSOR_SINK (sink);
413  type = GST_QUERY_TYPE (query);
414 
415  GST_DEBUG_OBJECT (self, "Received %s query: %" GST_PTR_FORMAT,
416  GST_QUERY_TYPE_NAME (query), query);
417 
418  switch (type) {
419  case GST_QUERY_SEEKING:
421  gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
422  gst_query_set_seeking (query, format, FALSE, 0, -1);
423  return TRUE;
424 
425  default:
426  break;
427  }
428 
429  return GST_BASE_SINK_CLASS (parent_class)->query (sink, query);
430 }
431 
437 static GstFlowReturn
438 gst_tensor_sink_render (GstBaseSink * sink, GstBuffer * buffer)
439 {
440  GstTensorSink *self;
441 
442  self = GST_TENSOR_SINK (sink);
443  gst_tensor_sink_render_buffer (self, buffer);
444 
445  return GST_FLOW_OK;
446 }
447 
453 static GstFlowReturn
454 gst_tensor_sink_render_list (GstBaseSink * sink, GstBufferList * buffer_list)
455 {
456  GstTensorSink *self;
457  GstBuffer *buffer;
458  guint i;
459  guint num_buffers;
460 
461  self = GST_TENSOR_SINK (sink);
462  num_buffers = gst_buffer_list_length (buffer_list);
463 
464  for (i = 0; i < num_buffers; i++) {
465  buffer = gst_buffer_list_get (buffer_list, i);
466  gst_tensor_sink_render_buffer (self, buffer);
467  }
468 
469  return GST_FLOW_OK;
470 }
471 
478 static void
479 gst_tensor_sink_render_buffer (GstTensorSink * self, GstBuffer * buffer)
480 {
481  GstClockTime now = GST_CLOCK_TIME_NONE;
482  guint signal_rate;
483  gboolean notify = FALSE;
484 
485  g_return_if_fail (GST_IS_TENSOR_SINK (self));
486 
487  signal_rate = gst_tensor_sink_get_signal_rate (self);
488 
489  if (signal_rate) {
490  GstClock *clock;
491  GstClockTime render_time;
492  GstClockTime last_render_time;
493 
494  clock = gst_element_get_clock (GST_ELEMENT (self));
495 
496  if (clock) {
497  now = gst_clock_get_time (clock);
498  last_render_time = gst_tensor_sink_get_last_render_time (self);
499 
501  render_time = (1000 / signal_rate) * GST_MSECOND + last_render_time;
502 
503  if (!GST_CLOCK_TIME_IS_VALID (last_render_time) ||
504  GST_CLOCK_DIFF (now, render_time) <= 0) {
506  notify = TRUE;
507  }
508 
509  gst_object_unref (clock);
510  }
511  } else {
513  notify = TRUE;
514  }
515 
516  if (notify) {
518 
519  if (gst_tensor_sink_get_emit_signal (self)) {
520  silent_debug (self,
521  "Emit signal for new data [%" GST_TIME_FORMAT "] rate [%d]",
522  GST_TIME_ARGS (now), signal_rate);
523 
524  g_signal_emit (self, _tensor_sink_signals[SIGNAL_NEW_DATA], 0, buffer);
525  }
526  }
527 
528  silent_debug_timestamp (self, buffer);
529 }
530 
534 static void
536 {
537  g_return_if_fail (GST_IS_TENSOR_SINK (self));
538 
539  g_mutex_lock (&self->mutex);
540  self->last_render_time = now;
541  g_mutex_unlock (&self->mutex);
542 }
543 
547 static GstClockTime
549 {
550  GstClockTime last_render_time;
551 
552  g_return_val_if_fail (GST_IS_TENSOR_SINK (self), GST_CLOCK_TIME_NONE);
553 
554  g_mutex_lock (&self->mutex);
555  last_render_time = self->last_render_time;
556  g_mutex_unlock (&self->mutex);
557 
558  return last_render_time;
559 }
560 
564 static void
566 {
567  g_return_if_fail (GST_IS_TENSOR_SINK (self));
568 
569  GST_INFO_OBJECT (self, "set signal_rate to %d", rate);
570  g_mutex_lock (&self->mutex);
571  self->signal_rate = rate;
572  g_mutex_unlock (&self->mutex);
573 }
574 
578 static guint
580 {
581  guint rate;
582 
583  g_return_val_if_fail (GST_IS_TENSOR_SINK (self), 0);
584 
585  g_mutex_lock (&self->mutex);
586  rate = self->signal_rate;
587  g_mutex_unlock (&self->mutex);
588 
589  return rate;
590 }
591 
595 static void
597 {
598  g_return_if_fail (GST_IS_TENSOR_SINK (self));
599 
600  GST_INFO_OBJECT (self, "set emit_signal to %d", emit);
601  g_mutex_lock (&self->mutex);
602  self->emit_signal = emit;
603  g_mutex_unlock (&self->mutex);
604 }
605 
609 static gboolean
611 {
612  gboolean res;
613 
614  g_return_val_if_fail (GST_IS_TENSOR_SINK (self), FALSE);
615 
616  g_mutex_lock (&self->mutex);
617  res = self->emit_signal;
618  g_mutex_unlock (&self->mutex);
619 
620  return res;
621 }
622 
626 static void
627 gst_tensor_sink_set_silent (GstTensorSink * self, gboolean silent)
628 {
629  g_return_if_fail (GST_IS_TENSOR_SINK (self));
630 
631  GST_INFO_OBJECT (self, "set silent to %d", silent);
632  self->silent = silent;
633 }
634 
638 static gboolean
640 {
641  g_return_val_if_fail (GST_IS_TENSOR_SINK (self), TRUE);
642 
643  return self->silent;
644 }
gst_tensor_sink_render
static GstFlowReturn gst_tensor_sink_render(GstBaseSink *sink, GstBuffer *buffer)
Handle buffer.
Definition: gsttensor_sink.c:438
GST_TENSOR_SINK
#define GST_TENSOR_SINK(obj)
Definition: gsttensor_sink.h:38
DEFAULT_SYNC
#define DEFAULT_SYNC
Flag to synchronize on the clock (Default FALSE). It may be delayed with tensor_filter element,...
Definition: gsttensor_sink.c:104
GST_TENSOR_CAP_DEFAULT
#define GST_TENSOR_CAP_DEFAULT
Default static capability for other/tensor.
Definition: tensor_typedef.h:78
LAST_SIGNAL
@ LAST_SIGNAL
Definition: gsttensor_sink.c:63
SIGNAL_NEW_DATA
@ SIGNAL_NEW_DATA
Definition: gsttensor_sink.c:60
FALSE
return FALSE
Definition: gsttensor_transform.c:590
gst_tensor_sink_event
static gboolean gst_tensor_sink_event(GstBaseSink *sink, GstEvent *event)
Handle events.
Definition: gsttensor_sink.c:365
gst_tensor_sink_set_emit_signal
static void gst_tensor_sink_set_emit_signal(GstTensorSink *self, gboolean emit)
Setter for flag emit_signal.
Definition: gsttensor_sink.c:596
gst_tensor_sink_get_emit_signal
static gboolean gst_tensor_sink_get_emit_signal(GstTensorSink *self)
Getter for flag emit_signal.
Definition: gsttensor_sink.c:610
gst_tensor_sink_set_property
static void gst_tensor_sink_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
Setter for tensor_sink properties.
Definition: gsttensor_sink.c:284
_GstTensorSinkClass
GstTensorSinkClass data structure.
Definition: gsttensor_sink.h:71
SIGNAL_EOS
@ SIGNAL_EOS
Definition: gsttensor_sink.c:62
gst_tensor_sink_set_last_render_time
static void gst_tensor_sink_set_last_render_time(GstTensorSink *self, GstClockTime now)
Setter for value last_render_time.
Definition: gsttensor_sink.c:535
GST_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensor_sink_debug)
silent_debug
#define silent_debug(self,...)
Macro for debug message.
Definition: tensor_common.h:276
PROP_0
@ PROP_0
Definition: gsttensor_sink.c:71
gst_tensor_sink_get_signal_rate
static guint gst_tensor_sink_get_signal_rate(GstTensorSink *self)
Getter for value signal_rate.
Definition: gsttensor_sink.c:579
silent_debug_timestamp
#define silent_debug_timestamp(self, buf)
Definition: gsttensor_sink.c:44
SIGNAL_STREAM_START
@ SIGNAL_STREAM_START
Definition: gsttensor_sink.c:61
DEFAULT_SIGNAL_RATE
#define DEFAULT_SIGNAL_RATE
New data signals per second.
Definition: gsttensor_sink.c:85
DEFAULT_QOS
#define DEFAULT_QOS
Flag for qos event.
Definition: gsttensor_sink.c:97
gst_tensor_sink_get_property
static void gst_tensor_sink_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
Getter for tensor_sink properties.
Definition: gsttensor_sink.c:316
PROP_SIGNAL_RATE
@ PROP_SIGNAL_RATE
Definition: gsttensor_sink.c:72
gsttensor_sink.h
GStreamer plugin to handle tensor stream.
DEFAULT_SILENT
#define DEFAULT_SILENT
Flag to print minimized log.
Definition: gsttensor_sink.c:90
_tensor_sink_signals
static guint _tensor_sink_signals[LAST_SIGNAL]
Variable for signal ids.
Definition: gsttensor_sink.c:109
TRUE
return TRUE
Definition: gsttensor_if.c:897
GST_IS_TENSOR_SINK
#define GST_IS_TENSOR_SINK(obj)
Definition: gsttensor_sink.h:42
gst_tensor_sink_finalize
static void gst_tensor_sink_finalize(GObject *object)
Function to finalize instance.
Definition: gsttensor_sink.c:348
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorSink, gst_tensor_sink, GST_TYPE_BASE_SINK)
GST_TENSORS_CAP_MAKE
#define GST_TENSORS_CAP_MAKE(fmt)
Caps string for the caps template of tensor stream. format should be a string that describes the data...
Definition: tensor_typedef.h:97
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_sink.c:74
gst_tensor_sink_render_list
static GstFlowReturn gst_tensor_sink_render_list(GstBaseSink *sink, GstBufferList *buffer_list)
Handle list of buffers.
Definition: gsttensor_sink.c:454
gst_tensor_sink_query
static gboolean gst_tensor_sink_query(GstBaseSink *sink, GstQuery *query)
Handle queries.
Definition: gsttensor_sink.c:406
_GstTensorSink
GstTensorSink data structure.
Definition: gsttensor_sink.h:55
DEFAULT_EMIT_SIGNAL
#define DEFAULT_EMIT_SIGNAL
Flag to emit signals.
Definition: gsttensor_sink.c:80
gst_tensor_sink_init
static void gst_tensor_sink_init(GstTensorSink *self)
Initialize tensor_sink element.
Definition: gsttensor_sink.c:257
gst_tensor_sink_set_signal_rate
static void gst_tensor_sink_set_signal_rate(GstTensorSink *self, guint rate)
Setter for value signal_rate.
Definition: gsttensor_sink.c:565
gst_tensor_sink_render_buffer
static void gst_tensor_sink_render_buffer(GstTensorSink *self, GstBuffer *buffer)
Handle buffer data.
Definition: gsttensor_sink.c:479
gst_tensor_sink_get_silent
static gboolean gst_tensor_sink_get_silent(GstTensorSink *self)
Getter for flag silent.
Definition: gsttensor_sink.c:639
gst_tensor_sink_class_init
static void gst_tensor_sink_class_init(GstTensorSinkClass *klass)
Initialize tensor_sink class.
Definition: gsttensor_sink.c:147
gst_tensor_sink_get_last_render_time
static GstClockTime gst_tensor_sink_get_last_render_time(GstTensorSink *self)
Getter for value last_render_time.
Definition: gsttensor_sink.c:548
gst_tensor_sink_set_silent
static void gst_tensor_sink_set_silent(GstTensorSink *self, gboolean silent)
Setter for flag silent.
Definition: gsttensor_sink.c:627
PROP_EMIT_SIGNAL
@ PROP_EMIT_SIGNAL
Definition: gsttensor_sink.c:73
type
svtc_1 type
Definition: gsttensor_if.c:843