Line data Source code
1 : /**
2 : * GStreamer
3 : * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
4 : * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
5 : * Copyright (C) 2018 Samsung Electronics Co., Ltd.
6 : *
7 : * This library is free software; you can redistribute it and/or
8 : * modify it under the terms of the GNU Library General Public
9 : * License as published by the Free Software Foundation;
10 : * version 2.1 of the License.
11 : *
12 : * This library is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : * Library General Public License for more details.
16 : */
17 :
18 : /**
19 : * SECTION:element-tensor_sink
20 : *
21 : * Sink element to handle tensor stream
22 : *
23 : * @file gsttensor_sink.c
24 : * @date 15 June 2018
25 : * @brief GStreamer plugin to handle tensor stream
26 : * @see https://github.com/nnstreamer/nnstreamer
27 : * @author Jaeyun Jung <jy1210.jung@samsung.com>
28 : * @bug No known bugs except for NYI items
29 : */
30 :
31 : #ifdef HAVE_CONFIG_H
32 : #include <config.h>
33 : #endif
34 :
35 : #include "gsttensor_sink.h"
36 :
37 : /**
38 : * @brief Macro for debug mode.
39 : */
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 :
55 : /**
56 : * @brief tensor_sink signals.
57 : */
58 : enum
59 : {
60 : SIGNAL_NEW_DATA,
61 : SIGNAL_STREAM_START,
62 : SIGNAL_EOS,
63 : LAST_SIGNAL
64 : };
65 :
66 : /**
67 : * @brief tensor_sink properties.
68 : */
69 : enum
70 : {
71 : PROP_0,
72 : PROP_SIGNAL_RATE,
73 : PROP_EMIT_SIGNAL,
74 : PROP_SILENT
75 : };
76 :
77 : /**
78 : * @brief Flag to emit signals.
79 : */
80 : #define DEFAULT_EMIT_SIGNAL TRUE
81 :
82 : /**
83 : * @brief New data signals per second.
84 : */
85 : #define DEFAULT_SIGNAL_RATE 0
86 :
87 : /**
88 : * @brief Flag to print minimized log.
89 : */
90 : #define DEFAULT_SILENT TRUE
91 :
92 : /**
93 : * @brief Flag for qos event.
94 : *
95 : * See GstBaseSink::qos property for more details.
96 : */
97 : #define DEFAULT_QOS TRUE
98 :
99 : /**
100 : * @brief Flag to synchronize on the clock (Default FALSE).
101 : * It may be delayed with tensor_filter element, to invoke neural network model.
102 : * See GstBaseSink::sync property for more details.
103 : */
104 : #define DEFAULT_SYNC FALSE
105 :
106 : /**
107 : * @brief Variable for signal ids.
108 : */
109 : static guint _tensor_sink_signals[LAST_SIGNAL] = { 0 };
110 :
111 : /** GObject method implementation */
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 :
118 : /** GstBaseSink method implementation */
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 :
126 : /** internal functions */
127 : static void gst_tensor_sink_render_buffer (GstTensorSink * self,
128 : GstBuffer * buffer);
129 : static void gst_tensor_sink_set_last_render_time (GstTensorSink * self,
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);
134 : static void gst_tensor_sink_set_emit_signal (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 38339 : G_DEFINE_TYPE (GstTensorSink, gst_tensor_sink, GST_TYPE_BASE_SINK);
142 :
143 : /**
144 : * @brief Initialize tensor_sink class.
145 : */
146 : static void
147 19 : gst_tensor_sink_class_init (GstTensorSinkClass * klass)
148 : {
149 : GObjectClass *gobject_class;
150 : GstElementClass *element_class;
151 : GstBaseSinkClass *bsink_class;
152 : GstPadTemplate *pad_template;
153 : GstCaps *pad_caps;
154 :
155 19 : GST_DEBUG_CATEGORY_INIT (gst_tensor_sink_debug, "tensor_sink", 0,
156 : "Sink element to handle tensor stream");
157 :
158 19 : gobject_class = G_OBJECT_CLASS (klass);
159 19 : element_class = GST_ELEMENT_CLASS (klass);
160 19 : bsink_class = GST_BASE_SINK_CLASS (klass);
161 :
162 : /** GObject methods */
163 19 : gobject_class->set_property = gst_tensor_sink_set_property;
164 19 : gobject_class->get_property = gst_tensor_sink_get_property;
165 19 : gobject_class->finalize = gst_tensor_sink_finalize;
166 :
167 : /**
168 : * GstTensorSink::signal-rate:
169 : *
170 : * The number of new data signals per second (Default 0 for unlimited, MAX 500)
171 : * If signal-rate is larger than 0, GstTensorSink calculates the time to emit a signal with this property.
172 : * If set 0 (default value), all the received buffers will be passed to the application.
173 : *
174 : * Please note that this property does not guarantee the periodic signals.
175 : * This means if GstTensorSink cannot get the buffers in time, it will pass all the buffers. (working like default 0)
176 : */
177 19 : 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 :
182 : /**
183 : * GstTensorSink::emit-signal:
184 : *
185 : * The flag to emit the signals for new data, stream start, and eos.
186 : */
187 19 : 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 :
192 : /**
193 : * GstTensorSink::silent:
194 : *
195 : * The flag to enable/disable debugging messages.
196 : */
197 19 : 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 :
201 : /**
202 : * GstTensorSink::new-data:
203 : *
204 : * Signal to get the buffer from GstTensorSink.
205 : */
206 19 : _tensor_sink_signals[SIGNAL_NEW_DATA] =
207 19 : 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 :
211 : /**
212 : * GstTensorSink::stream-start:
213 : *
214 : * Signal to indicate the start of a new stream.
215 : * Optional. An application can use this signal to detect the start of a new stream, instead of the message GST_MESSAGE_STREAM_START from pipeline.
216 : */
217 19 : _tensor_sink_signals[SIGNAL_STREAM_START] =
218 19 : 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 :
222 : /**
223 : * GstTensorSink::eos:
224 : *
225 : * Signal to indicate the end-of-stream.
226 : * Optional. An application can use this signal to detect the EOS (end-of-stream), instead of the message GST_MESSAGE_EOS from pipeline.
227 : */
228 19 : _tensor_sink_signals[SIGNAL_EOS] =
229 19 : 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 19 : 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 :
238 : /** pad template */
239 19 : pad_caps = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT ";"
240 : GST_TENSORS_CAP_MAKE ("{ static, flexible, sparse }"));
241 19 : pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
242 : pad_caps);
243 19 : gst_element_class_add_pad_template (element_class, pad_template);
244 19 : gst_caps_unref (pad_caps);
245 :
246 : /** GstBaseSink methods */
247 19 : bsink_class->event = GST_DEBUG_FUNCPTR (gst_tensor_sink_event);
248 19 : bsink_class->query = GST_DEBUG_FUNCPTR (gst_tensor_sink_query);
249 19 : bsink_class->render = GST_DEBUG_FUNCPTR (gst_tensor_sink_render);
250 19 : bsink_class->render_list = GST_DEBUG_FUNCPTR (gst_tensor_sink_render_list);
251 19 : }
252 :
253 : /**
254 : * @brief Initialize tensor_sink element.
255 : */
256 : static void
257 213 : gst_tensor_sink_init (GstTensorSink * self)
258 : {
259 : GstBaseSink *bsink;
260 :
261 213 : bsink = GST_BASE_SINK (self);
262 :
263 213 : g_mutex_init (&self->mutex);
264 :
265 : /** init properties */
266 213 : self->silent = DEFAULT_SILENT;
267 213 : self->emit_signal = DEFAULT_EMIT_SIGNAL;
268 213 : self->signal_rate = DEFAULT_SIGNAL_RATE;
269 213 : self->last_render_time = GST_CLOCK_TIME_NONE;
270 :
271 : /** enable qos */
272 213 : gst_base_sink_set_qos_enabled (bsink, DEFAULT_QOS);
273 :
274 : /* set 'sync' to synchronize on the clock or not */
275 213 : gst_base_sink_set_sync (bsink, DEFAULT_SYNC);
276 213 : }
277 :
278 : /**
279 : * @brief Setter for tensor_sink properties.
280 : *
281 : * GObject method implementation.
282 : */
283 : static void
284 6 : gst_tensor_sink_set_property (GObject * object, guint prop_id,
285 : const GValue * value, GParamSpec * pspec)
286 : {
287 : GstTensorSink *self;
288 :
289 6 : self = GST_TENSOR_SINK (object);
290 :
291 6 : switch (prop_id) {
292 2 : case PROP_SIGNAL_RATE:
293 2 : gst_tensor_sink_set_signal_rate (self, g_value_get_uint (value));
294 2 : break;
295 :
296 2 : case PROP_EMIT_SIGNAL:
297 2 : gst_tensor_sink_set_emit_signal (self, g_value_get_boolean (value));
298 2 : break;
299 :
300 2 : case PROP_SILENT:
301 2 : gst_tensor_sink_set_silent (self, g_value_get_boolean (value));
302 2 : break;
303 :
304 0 : default:
305 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
306 0 : break;
307 : }
308 6 : }
309 :
310 : /**
311 : * @brief Getter for tensor_sink properties.
312 : *
313 : * GObject method implementation.
314 : */
315 : static void
316 6 : gst_tensor_sink_get_property (GObject * object, guint prop_id,
317 : GValue * value, GParamSpec * pspec)
318 : {
319 : GstTensorSink *self;
320 :
321 6 : self = GST_TENSOR_SINK (object);
322 :
323 6 : switch (prop_id) {
324 2 : case PROP_SIGNAL_RATE:
325 2 : g_value_set_uint (value, gst_tensor_sink_get_signal_rate (self));
326 2 : break;
327 :
328 2 : case PROP_EMIT_SIGNAL:
329 2 : g_value_set_boolean (value, gst_tensor_sink_get_emit_signal (self));
330 2 : break;
331 :
332 2 : case PROP_SILENT:
333 2 : g_value_set_boolean (value, gst_tensor_sink_get_silent (self));
334 2 : break;
335 :
336 0 : default:
337 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
338 0 : break;
339 : }
340 6 : }
341 :
342 : /**
343 : * @brief Function to finalize instance.
344 : *
345 : * GObject method implementation.
346 : */
347 : static void
348 178 : gst_tensor_sink_finalize (GObject * object)
349 : {
350 : GstTensorSink *self;
351 :
352 178 : self = GST_TENSOR_SINK (object);
353 :
354 178 : g_mutex_clear (&self->mutex);
355 :
356 178 : G_OBJECT_CLASS (parent_class)->finalize (object);
357 178 : }
358 :
359 : /**
360 : * @brief Handle events.
361 : *
362 : * GstBaseSink method implementation.
363 : */
364 : static gboolean
365 631 : gst_tensor_sink_event (GstBaseSink * sink, GstEvent * event)
366 : {
367 : GstTensorSink *self;
368 : GstEventType type;
369 :
370 631 : self = GST_TENSOR_SINK (sink);
371 631 : type = GST_EVENT_TYPE (event);
372 :
373 631 : GST_DEBUG_OBJECT (self, "Received %s event: %" GST_PTR_FORMAT,
374 : GST_EVENT_TYPE_NAME (event), event);
375 :
376 631 : switch (type) {
377 175 : case GST_EVENT_STREAM_START:
378 175 : if (gst_tensor_sink_get_emit_signal (self)) {
379 174 : silent_debug (self, "Emit signal for stream start");
380 :
381 174 : g_signal_emit (self, _tensor_sink_signals[SIGNAL_STREAM_START], 0);
382 : }
383 175 : break;
384 :
385 137 : case GST_EVENT_EOS:
386 137 : if (gst_tensor_sink_get_emit_signal (self)) {
387 136 : silent_debug (self, "Emit signal for eos");
388 :
389 136 : g_signal_emit (self, _tensor_sink_signals[SIGNAL_EOS], 0);
390 : }
391 137 : break;
392 :
393 319 : default:
394 319 : break;
395 : }
396 :
397 631 : return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
398 : }
399 :
400 : /**
401 : * @brief Handle queries.
402 : *
403 : * GstBaseSink method implementation.
404 : */
405 : static gboolean
406 1475 : gst_tensor_sink_query (GstBaseSink * sink, GstQuery * query)
407 : {
408 : GstTensorSink *self;
409 : GstQueryType type;
410 : GstFormat format;
411 :
412 1475 : self = GST_TENSOR_SINK (sink);
413 1475 : type = GST_QUERY_TYPE (query);
414 :
415 1475 : GST_DEBUG_OBJECT (self, "Received %s query: %" GST_PTR_FORMAT,
416 : GST_QUERY_TYPE_NAME (query), query);
417 :
418 1475 : switch (type) {
419 0 : case GST_QUERY_SEEKING:
420 : /** tensor sink does not support seeking */
421 0 : gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
422 0 : gst_query_set_seeking (query, format, FALSE, 0, -1);
423 1475 : return TRUE;
424 :
425 1475 : default:
426 1475 : break;
427 : }
428 :
429 1475 : return GST_BASE_SINK_CLASS (parent_class)->query (sink, query);
430 : }
431 :
432 : /**
433 : * @brief Handle buffer.
434 : *
435 : * GstBaseSink method implementation.
436 : */
437 : static GstFlowReturn
438 6968 : gst_tensor_sink_render (GstBaseSink * sink, GstBuffer * buffer)
439 : {
440 : GstTensorSink *self;
441 :
442 6968 : self = GST_TENSOR_SINK (sink);
443 6968 : gst_tensor_sink_render_buffer (self, buffer);
444 :
445 6968 : return GST_FLOW_OK;
446 : }
447 :
448 : /**
449 : * @brief Handle list of buffers.
450 : *
451 : * GstBaseSink method implementation.
452 : */
453 : static GstFlowReturn
454 0 : 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 0 : self = GST_TENSOR_SINK (sink);
462 0 : num_buffers = gst_buffer_list_length (buffer_list);
463 :
464 0 : for (i = 0; i < num_buffers; i++) {
465 0 : buffer = gst_buffer_list_get (buffer_list, i);
466 0 : gst_tensor_sink_render_buffer (self, buffer);
467 : }
468 :
469 0 : return GST_FLOW_OK;
470 : }
471 :
472 : /**
473 : * @brief Handle buffer data.
474 : * @return None
475 : * @param self pointer to GstTensorSink
476 : * @param buffer pointer to GstBuffer to be handled
477 : */
478 : static void
479 6968 : gst_tensor_sink_render_buffer (GstTensorSink * self, GstBuffer * buffer)
480 : {
481 6968 : GstClockTime now = GST_CLOCK_TIME_NONE;
482 : guint signal_rate;
483 6968 : gboolean notify = FALSE;
484 :
485 6968 : g_return_if_fail (GST_IS_TENSOR_SINK (self));
486 :
487 6968 : signal_rate = gst_tensor_sink_get_signal_rate (self);
488 :
489 6968 : if (signal_rate) {
490 : GstClock *clock;
491 : GstClockTime render_time;
492 : GstClockTime last_render_time;
493 :
494 6 : clock = gst_element_get_clock (GST_ELEMENT (self));
495 :
496 6 : if (clock) {
497 6 : now = gst_clock_get_time (clock);
498 6 : last_render_time = gst_tensor_sink_get_last_render_time (self);
499 :
500 : /** time for next signal */
501 6 : render_time = (1000 / signal_rate) * GST_MSECOND + last_render_time;
502 :
503 6 : if (!GST_CLOCK_TIME_IS_VALID (last_render_time) ||
504 5 : GST_CLOCK_DIFF (now, render_time) <= 0) {
505 : /** send data after render time, or firstly received buffer */
506 1 : notify = TRUE;
507 : }
508 :
509 6 : gst_object_unref (clock);
510 : }
511 : } else {
512 : /** send data if signal rate is 0 */
513 6962 : notify = TRUE;
514 : }
515 :
516 6968 : if (notify) {
517 6963 : gst_tensor_sink_set_last_render_time (self, now);
518 :
519 6963 : if (gst_tensor_sink_get_emit_signal (self)) {
520 6958 : silent_debug (self,
521 : "Emit signal for new data [%" GST_TIME_FORMAT "] rate [%d]",
522 : GST_TIME_ARGS (now), signal_rate);
523 :
524 6958 : g_signal_emit (self, _tensor_sink_signals[SIGNAL_NEW_DATA], 0, buffer);
525 : }
526 : }
527 :
528 6968 : silent_debug_timestamp (self, buffer);
529 : }
530 :
531 : /**
532 : * @brief Setter for value last_render_time.
533 : */
534 : static void
535 6963 : gst_tensor_sink_set_last_render_time (GstTensorSink * self, GstClockTime now)
536 : {
537 6963 : g_return_if_fail (GST_IS_TENSOR_SINK (self));
538 :
539 6963 : g_mutex_lock (&self->mutex);
540 6963 : self->last_render_time = now;
541 6963 : g_mutex_unlock (&self->mutex);
542 : }
543 :
544 : /**
545 : * @brief Getter for value last_render_time.
546 : */
547 : static GstClockTime
548 6 : gst_tensor_sink_get_last_render_time (GstTensorSink * self)
549 : {
550 : GstClockTime last_render_time;
551 :
552 6 : g_return_val_if_fail (GST_IS_TENSOR_SINK (self), GST_CLOCK_TIME_NONE);
553 :
554 6 : g_mutex_lock (&self->mutex);
555 6 : last_render_time = self->last_render_time;
556 6 : g_mutex_unlock (&self->mutex);
557 :
558 6 : return last_render_time;
559 : }
560 :
561 : /**
562 : * @brief Setter for value signal_rate.
563 : */
564 : static void
565 2 : gst_tensor_sink_set_signal_rate (GstTensorSink * self, guint rate)
566 : {
567 2 : g_return_if_fail (GST_IS_TENSOR_SINK (self));
568 :
569 2 : GST_INFO_OBJECT (self, "set signal_rate to %d", rate);
570 2 : g_mutex_lock (&self->mutex);
571 2 : self->signal_rate = rate;
572 2 : g_mutex_unlock (&self->mutex);
573 : }
574 :
575 : /**
576 : * @brief Getter for value signal_rate.
577 : */
578 : static guint
579 6970 : gst_tensor_sink_get_signal_rate (GstTensorSink * self)
580 : {
581 : guint rate;
582 :
583 6970 : g_return_val_if_fail (GST_IS_TENSOR_SINK (self), 0);
584 :
585 6970 : g_mutex_lock (&self->mutex);
586 6970 : rate = self->signal_rate;
587 6970 : g_mutex_unlock (&self->mutex);
588 :
589 6970 : return rate;
590 : }
591 :
592 : /**
593 : * @brief Setter for flag emit_signal.
594 : */
595 : static void
596 2 : gst_tensor_sink_set_emit_signal (GstTensorSink * self, gboolean emit)
597 : {
598 2 : g_return_if_fail (GST_IS_TENSOR_SINK (self));
599 :
600 2 : GST_INFO_OBJECT (self, "set emit_signal to %d", emit);
601 2 : g_mutex_lock (&self->mutex);
602 2 : self->emit_signal = emit;
603 2 : g_mutex_unlock (&self->mutex);
604 : }
605 :
606 : /**
607 : * @brief Getter for flag emit_signal.
608 : */
609 : static gboolean
610 7277 : gst_tensor_sink_get_emit_signal (GstTensorSink * self)
611 : {
612 : gboolean res;
613 :
614 7277 : g_return_val_if_fail (GST_IS_TENSOR_SINK (self), FALSE);
615 :
616 7277 : g_mutex_lock (&self->mutex);
617 7277 : res = self->emit_signal;
618 7277 : g_mutex_unlock (&self->mutex);
619 :
620 7277 : return res;
621 : }
622 :
623 : /**
624 : * @brief Setter for flag silent.
625 : */
626 : static void
627 2 : gst_tensor_sink_set_silent (GstTensorSink * self, gboolean silent)
628 : {
629 2 : g_return_if_fail (GST_IS_TENSOR_SINK (self));
630 :
631 2 : GST_INFO_OBJECT (self, "set silent to %d", silent);
632 2 : self->silent = silent;
633 : }
634 :
635 : /**
636 : * @brief Getter for flag silent.
637 : */
638 : static gboolean
639 2 : gst_tensor_sink_get_silent (GstTensorSink * self)
640 : {
641 2 : g_return_val_if_fail (GST_IS_TENSOR_SINK (self), TRUE);
642 :
643 2 : return self->silent;
644 : }
|