1 /* GStreamer
2 * Copyright (C) 2007 David Schleef <ds@schleef.org>
3 * (C) 2008 Wim Taymans <wim.taymans@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20 /**
21 * SECTION:gstappsink
22 * @title: GstAppSink
23 * @short_description: Easy way for applications to extract samples from a
24 * pipeline
25 * @see_also: #GstSample, #GstBaseSink, appsrc
26 *
27 * Appsink is a sink plugin that supports many different methods for making
28 * the application get a handle on the GStreamer data in a pipeline. Unlike
29 * most GStreamer elements, Appsink provides external API functions.
30 *
31 * appsink can be used by linking to the gstappsink.h header file to access the
32 * methods or by using the appsink action signals and properties.
33 *
34 * The normal way of retrieving samples from appsink is by using the
35 * gst_app_sink_pull_sample() and gst_app_sink_pull_preroll() methods.
36 * These methods block until a sample becomes available in the sink or when the
37 * sink is shut down or reaches EOS. There are also timed variants of these
38 * methods, gst_app_sink_try_pull_sample() and gst_app_sink_try_pull_preroll(),
39 * which accept a timeout parameter to limit the amount of time to wait.
40 *
41 * Appsink will internally use a queue to collect buffers from the streaming
42 * thread. If the application is not pulling samples fast enough, this queue
43 * will consume a lot of memory over time. The "max-buffers" property can be
44 * used to limit the queue size. The "drop" property controls whether the
45 * streaming thread blocks or if older buffers are dropped when the maximum
46 * queue size is reached. Note that blocking the streaming thread can negatively
47 * affect real-time performance and should be avoided.
48 *
49 * If a blocking behaviour is not desirable, setting the "emit-signals" property
50 * to %TRUE will make appsink emit the "new-sample" and "new-preroll" signals
51 * when a sample can be pulled without blocking.
52 *
53 * The "caps" property on appsink can be used to control the formats that
54 * appsink can receive. This property can contain non-fixed caps, the format of
55 * the pulled samples can be obtained by getting the sample caps.
56 *
57 * If one of the pull-preroll or pull-sample methods return %NULL, the appsink
58 * is stopped or in the EOS state. You can check for the EOS state with the
59 * "eos" property or with the gst_app_sink_is_eos() method.
60 *
61 * The eos signal can also be used to be informed when the EOS state is reached
62 * to avoid polling.
63 */
64
65 #ifdef HAVE_CONFIG_H
66 #include "config.h"
67 #endif
68
69 #include <gst/gst.h>
70 #include <gst/base/base.h>
71
72 #include <string.h>
73
74 #include "gstappsink.h"
75
76 typedef enum
77 {
78 NOONE_WAITING = 0,
79 STREAM_WAITING = 1 << 0, /* streaming thread is waiting for application thread */
80 APP_WAITING = 1 << 1, /* application thread is waiting for streaming thread */
81 } GstAppSinkWaitStatus;
82
83 typedef struct
84 {
85 GstAppSinkCallbacks callbacks;
86 gpointer user_data;
87 GDestroyNotify destroy_notify;
88 gint ref_count;
89 } Callbacks;
90
91 static Callbacks *
callbacks_ref(Callbacks * callbacks)92 callbacks_ref (Callbacks * callbacks)
93 {
94 g_atomic_int_inc (&callbacks->ref_count);
95
96 return callbacks;
97 }
98
99 static void
callbacks_unref(Callbacks * callbacks)100 callbacks_unref (Callbacks * callbacks)
101 {
102 if (!g_atomic_int_dec_and_test (&callbacks->ref_count))
103 return;
104
105 if (callbacks->destroy_notify)
106 callbacks->destroy_notify (callbacks->user_data);
107
108 g_free (callbacks);
109 }
110
111 struct _GstAppSinkPrivate
112 {
113 GstCaps *caps;
114 gboolean emit_signals;
115 guint num_buffers;
116 guint num_events;
117 guint max_buffers;
118 gboolean drop;
119 gboolean wait_on_eos;
120 GstAppSinkWaitStatus wait_status;
121
122 GCond cond;
123 GMutex mutex;
124 GstQueueArray *queue;
125 GstBuffer *preroll_buffer;
126 GstCaps *preroll_caps;
127 GstCaps *last_caps;
128 GstSegment preroll_segment;
129 GstSegment last_segment;
130 gboolean flushing;
131 gboolean unlock;
132 gboolean started;
133 gboolean is_eos;
134 gboolean buffer_lists_supported;
135
136 Callbacks *callbacks;
137
138 GstSample *sample;
139 };
140
141 GST_DEBUG_CATEGORY_STATIC (app_sink_debug);
142 #define GST_CAT_DEFAULT app_sink_debug
143
144 enum
145 {
146 /* signals */
147 SIGNAL_EOS,
148 SIGNAL_NEW_PREROLL,
149 SIGNAL_NEW_SAMPLE,
150 SIGNAL_NEW_SERIALIZED_EVENT,
151
152 /* actions */
153 SIGNAL_PULL_PREROLL,
154 SIGNAL_PULL_SAMPLE,
155 SIGNAL_TRY_PULL_PREROLL,
156 SIGNAL_TRY_PULL_SAMPLE,
157 SIGNAL_TRY_PULL_OBJECT,
158
159 LAST_SIGNAL
160 };
161
162 #define DEFAULT_PROP_EOS TRUE
163 #define DEFAULT_PROP_EMIT_SIGNALS FALSE
164 #define DEFAULT_PROP_MAX_BUFFERS 0
165 #define DEFAULT_PROP_DROP FALSE
166 #define DEFAULT_PROP_WAIT_ON_EOS TRUE
167 #define DEFAULT_PROP_BUFFER_LIST FALSE
168
169 enum
170 {
171 PROP_0,
172 PROP_CAPS,
173 PROP_EOS,
174 PROP_EMIT_SIGNALS,
175 PROP_MAX_BUFFERS,
176 PROP_DROP,
177 PROP_WAIT_ON_EOS,
178 PROP_BUFFER_LIST,
179 PROP_LAST
180 };
181
182 static GstStaticPadTemplate gst_app_sink_template =
183 GST_STATIC_PAD_TEMPLATE ("sink",
184 GST_PAD_SINK,
185 GST_PAD_ALWAYS,
186 GST_STATIC_CAPS_ANY);
187
188 static void gst_app_sink_uri_handler_init (gpointer g_iface,
189 gpointer iface_data);
190
191 static void gst_app_sink_dispose (GObject * object);
192 static void gst_app_sink_finalize (GObject * object);
193
194 static void gst_app_sink_set_property (GObject * object, guint prop_id,
195 const GValue * value, GParamSpec * pspec);
196 static void gst_app_sink_get_property (GObject * object, guint prop_id,
197 GValue * value, GParamSpec * pspec);
198
199 static gboolean gst_app_sink_unlock_start (GstBaseSink * bsink);
200 static gboolean gst_app_sink_unlock_stop (GstBaseSink * bsink);
201 static gboolean gst_app_sink_start (GstBaseSink * psink);
202 static gboolean gst_app_sink_stop (GstBaseSink * psink);
203 static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
204 static gboolean gst_app_sink_query (GstBaseSink * bsink, GstQuery * query);
205 static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
206 GstBuffer * buffer);
207 static GstFlowReturn gst_app_sink_render_common (GstBaseSink * psink,
208 GstMiniObject * data, gboolean is_list);
209 static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
210 GstBuffer * buffer);
211 static GstFlowReturn gst_app_sink_render_list (GstBaseSink * psink,
212 GstBufferList * list);
213 static gboolean gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps);
214 static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink, GstCaps * filter);
215
216 static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
217
218 #define gst_app_sink_parent_class parent_class
219 G_DEFINE_TYPE_WITH_CODE (GstAppSink, gst_app_sink, GST_TYPE_BASE_SINK,
220 G_ADD_PRIVATE (GstAppSink)
221 G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
222 gst_app_sink_uri_handler_init));
223
224 static void
gst_app_sink_class_init(GstAppSinkClass * klass)225 gst_app_sink_class_init (GstAppSinkClass * klass)
226 {
227 GObjectClass *gobject_class = (GObjectClass *) klass;
228 GstElementClass *element_class = (GstElementClass *) klass;
229 GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
230
231 GST_DEBUG_CATEGORY_INIT (app_sink_debug, "appsink", 0, "appsink element");
232
233 gobject_class->dispose = gst_app_sink_dispose;
234 gobject_class->finalize = gst_app_sink_finalize;
235
236 gobject_class->set_property = gst_app_sink_set_property;
237 gobject_class->get_property = gst_app_sink_get_property;
238
239 g_object_class_install_property (gobject_class, PROP_CAPS,
240 g_param_spec_boxed ("caps", "Caps",
241 "The allowed caps for the sink pad", GST_TYPE_CAPS,
242 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
243
244 g_object_class_install_property (gobject_class, PROP_EOS,
245 g_param_spec_boolean ("eos", "EOS",
246 "Check if the sink is EOS or not started", DEFAULT_PROP_EOS,
247 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
248
249 g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
250 g_param_spec_boolean ("emit-signals", "Emit signals",
251 "Emit new-preroll and new-sample signals",
252 DEFAULT_PROP_EMIT_SIGNALS,
253 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
254
255 g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
256 g_param_spec_uint ("max-buffers", "Max Buffers",
257 "The maximum number of buffers to queue internally (0 = unlimited)",
258 0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
259 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
260
261 g_object_class_install_property (gobject_class, PROP_DROP,
262 g_param_spec_boolean ("drop", "Drop",
263 "Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
264 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
265
266 g_object_class_install_property (gobject_class, PROP_BUFFER_LIST,
267 g_param_spec_boolean ("buffer-list", "Buffer List",
268 "Use buffer lists", DEFAULT_PROP_BUFFER_LIST,
269 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
270 /**
271 * GstAppSink::wait-on-eos:
272 *
273 * Wait for all buffers to be processed after receiving an EOS.
274 *
275 * In cases where it is uncertain if an @appsink will have a consumer for its buffers
276 * when it receives an EOS, set to %FALSE to ensure that the @appsink will not hang.
277 *
278 * Since: 1.8
279 */
280 g_object_class_install_property (gobject_class, PROP_WAIT_ON_EOS,
281 g_param_spec_boolean ("wait-on-eos", "Wait on EOS",
282 "Wait for all buffers to be processed after receiving an EOS",
283 DEFAULT_PROP_WAIT_ON_EOS,
284 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
285
286 /**
287 * GstAppSink::eos:
288 * @appsink: the appsink element that emitted the signal
289 *
290 * Signal that the end-of-stream has been reached. This signal is emitted from
291 * the streaming thread.
292 */
293 gst_app_sink_signals[SIGNAL_EOS] =
294 g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
295 G_STRUCT_OFFSET (GstAppSinkClass, eos),
296 NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
297 /**
298 * GstAppSink::new-preroll:
299 * @appsink: the appsink element that emitted the signal
300 *
301 * Signal that a new preroll sample is available.
302 *
303 * This signal is emitted from the streaming thread and only when the
304 * "emit-signals" property is %TRUE.
305 *
306 * The new preroll sample can be retrieved with the "pull-preroll" action
307 * signal or gst_app_sink_pull_preroll() either from this signal callback
308 * or from any other thread.
309 *
310 * Note that this signal is only emitted when the "emit-signals" property is
311 * set to %TRUE, which it is not by default for performance reasons.
312 */
313 gst_app_sink_signals[SIGNAL_NEW_PREROLL] =
314 g_signal_new ("new-preroll", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
315 G_STRUCT_OFFSET (GstAppSinkClass, new_preroll),
316 NULL, NULL, NULL, GST_TYPE_FLOW_RETURN, 0, G_TYPE_NONE);
317 /**
318 * GstAppSink::new-sample:
319 * @appsink: the appsink element that emitted the signal
320 *
321 * Signal that a new sample is available.
322 *
323 * This signal is emitted from the streaming thread and only when the
324 * "emit-signals" property is %TRUE.
325 *
326 * The new sample can be retrieved with the "pull-sample" action
327 * signal or gst_app_sink_pull_sample() either from this signal callback
328 * or from any other thread.
329 *
330 * Note that this signal is only emitted when the "emit-signals" property is
331 * set to %TRUE, which it is not by default for performance reasons.
332 */
333 gst_app_sink_signals[SIGNAL_NEW_SAMPLE] =
334 g_signal_new ("new-sample", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
335 G_STRUCT_OFFSET (GstAppSinkClass, new_sample),
336 NULL, NULL, NULL, GST_TYPE_FLOW_RETURN, 0, G_TYPE_NONE);
337
338 /**
339 * GstAppSink::new-serialized-event:
340 * @appsink: the appsink element that emitted the signal
341 *
342 * Signal that a new downstream serialized event is available.
343 *
344 * This signal is emitted from the streaming thread and only when the
345 * "emit-signals" property is %TRUE.
346 *
347 * The new event can be retrieved with the "try-pull-object" action
348 * signal or gst_app_sink_pull_object() either from this signal callback
349 * or from any other thread.
350 *
351 * EOS will not be notified using this signal, use #GstAppSink::eos instead.
352 * EOS cannot be pulled either, use gst_app_sink_is_eos() to check for it.
353 *
354 * Note that this signal is only emitted when the "emit-signals" property is
355 * set to %TRUE, which it is not by default for performance reasons.
356 *
357 * The callback should return %TRUE if the event has been handled, which will
358 * skip basesink handling of the event, %FALSE otherwise.
359 *
360 * Since: 1.20
361 */
362 gst_app_sink_signals[SIGNAL_NEW_SERIALIZED_EVENT] =
363 g_signal_new ("new-serialized-event", G_TYPE_FROM_CLASS (klass),
364 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
365
366 /**
367 * GstAppSink::pull-preroll:
368 * @appsink: the appsink element to emit this signal on
369 *
370 * Get the last preroll sample in @appsink. This was the sample that caused the
371 * appsink to preroll in the PAUSED state.
372 *
373 * This function is typically used when dealing with a pipeline in the PAUSED
374 * state. Calling this function after doing a seek will give the sample right
375 * after the seek position.
376 *
377 * Calling this function will clear the internal reference to the preroll
378 * buffer.
379 *
380 * Note that the preroll sample will also be returned as the first sample
381 * when calling gst_app_sink_pull_sample() or the "pull-sample" action signal.
382 *
383 * If an EOS event was received before any buffers, this function returns
384 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
385 *
386 * This function blocks until a preroll sample or EOS is received or the appsink
387 * element is set to the READY/NULL state.
388 *
389 * Returns: a #GstSample or NULL when the appsink is stopped or EOS.
390 */
391 gst_app_sink_signals[SIGNAL_PULL_PREROLL] =
392 g_signal_new ("pull-preroll", G_TYPE_FROM_CLASS (klass),
393 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
394 pull_preroll), NULL, NULL, NULL, GST_TYPE_SAMPLE, 0, G_TYPE_NONE);
395 /**
396 * GstAppSink::pull-sample:
397 * @appsink: the appsink element to emit this signal on
398 *
399 * This function blocks until a sample or EOS becomes available or the appsink
400 * element is set to the READY/NULL state.
401 *
402 * This function will only return samples when the appsink is in the PLAYING
403 * state. All rendered samples will be put in a queue so that the application
404 * can pull samples at its own rate.
405 *
406 * Note that when the application does not pull samples fast enough, the
407 * queued samples could consume a lot of memory, especially when dealing with
408 * raw video frames. It's possible to control the behaviour of the queue with
409 * the "drop" and "max-buffers" properties.
410 *
411 * If an EOS event was received before any buffers, this function returns
412 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
413 *
414 * Returns: a #GstSample or NULL when the appsink is stopped or EOS.
415 */
416 gst_app_sink_signals[SIGNAL_PULL_SAMPLE] =
417 g_signal_new ("pull-sample", G_TYPE_FROM_CLASS (klass),
418 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
419 pull_sample), NULL, NULL, NULL, GST_TYPE_SAMPLE, 0, G_TYPE_NONE);
420
421 /**
422 * GstAppSink::try-pull-preroll:
423 * @appsink: the appsink element to emit this signal on
424 * @timeout: the maximum amount of time to wait for the preroll sample
425 *
426 * Get the last preroll sample in @appsink. This was the sample that caused the
427 * appsink to preroll in the PAUSED state.
428 *
429 * This function is typically used when dealing with a pipeline in the PAUSED
430 * state. Calling this function after doing a seek will give the sample right
431 * after the seek position.
432 *
433 * Calling this function will clear the internal reference to the preroll
434 * buffer.
435 *
436 * Note that the preroll sample will also be returned as the first sample
437 * when calling gst_app_sink_pull_sample() or the "pull-sample" action signal.
438 *
439 * If an EOS event was received before any buffers or the timeout expires,
440 * this function returns %NULL. Use gst_app_sink_is_eos () to check for the EOS
441 * condition.
442 *
443 * This function blocks until a preroll sample or EOS is received, the appsink
444 * element is set to the READY/NULL state, or the timeout expires.
445 *
446 * Returns: a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires.
447 *
448 * Since: 1.10
449 */
450 gst_app_sink_signals[SIGNAL_TRY_PULL_PREROLL] =
451 g_signal_new ("try-pull-preroll", G_TYPE_FROM_CLASS (klass),
452 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
453 G_STRUCT_OFFSET (GstAppSinkClass, try_pull_preroll), NULL, NULL, NULL,
454 GST_TYPE_SAMPLE, 1, GST_TYPE_CLOCK_TIME);
455 /**
456 * GstAppSink::try-pull-sample:
457 * @appsink: the appsink element to emit this signal on
458 * @timeout: the maximum amount of time to wait for a sample
459 *
460 * This function blocks until a sample or EOS becomes available or the appsink
461 * element is set to the READY/NULL state or the timeout expires.
462 *
463 * This function will only return samples when the appsink is in the PLAYING
464 * state. All rendered samples will be put in a queue so that the application
465 * can pull samples at its own rate.
466 *
467 * Note that when the application does not pull samples fast enough, the
468 * queued samples could consume a lot of memory, especially when dealing with
469 * raw video frames. It's possible to control the behaviour of the queue with
470 * the "drop" and "max-buffers" properties.
471 *
472 * If an EOS event was received before any buffers or the timeout expires,
473 * this function returns %NULL. Use gst_app_sink_is_eos () to check
474 * for the EOS condition.
475 *
476 * Returns: a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires.
477 *
478 * Since: 1.10
479 */
480 gst_app_sink_signals[SIGNAL_TRY_PULL_SAMPLE] =
481 g_signal_new ("try-pull-sample", G_TYPE_FROM_CLASS (klass),
482 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
483 G_STRUCT_OFFSET (GstAppSinkClass, try_pull_sample), NULL, NULL, NULL,
484 GST_TYPE_SAMPLE, 1, GST_TYPE_CLOCK_TIME);
485
486 /**
487 * GstAppSink::try-pull-object:
488 * @appsink: the appsink element to emit this signal on
489 * @timeout: the maximum amount of time to wait for a sample
490 *
491 * This function blocks until a sample or an event becomes available or the appsink
492 * element is set to the READY/NULL state or the timeout expires.
493 *
494 * This function will only return samples when the appsink is in the PLAYING
495 * state. All rendered samples and events will be put in a queue so that the application
496 * can pull them at its own rate.
497 * Events can be pulled when the appsink is in the READY, PAUSED or PLAYING state.
498 *
499 * Note that when the application does not pull samples fast enough, the
500 * queued samples could consume a lot of memory, especially when dealing with
501 * raw video frames. It's possible to control the behaviour of the queue with
502 * the "drop" and "max-buffers" properties.
503 *
504 * This function will only pull serialized events, excluding
505 * the EOS event for which this functions returns
506 * %NULL. Use gst_app_sink_is_eos() to check for the EOS condition.
507 *
508 * This signal is a variant of #GstAppSink::try-pull-sample: that can be used
509 * to handle incoming events as well as samples.
510 *
511 * Note that future releases may extend this API to return other object types
512 * so make sure that your code is checking for the actual type it is handling.
513 *
514 * Returns: (transfer full): a #GstSample or a #GstEvent or NULL when the appsink is stopped or EOS or the timeout expires.
515 *
516 * Since: 1.20
517 */
518 gst_app_sink_signals[SIGNAL_TRY_PULL_OBJECT] =
519 g_signal_new ("try-pull-object", G_TYPE_FROM_CLASS (klass),
520 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
521 G_STRUCT_OFFSET (GstAppSinkClass, try_pull_object), NULL, NULL, NULL,
522 GST_TYPE_MINI_OBJECT, 1, GST_TYPE_CLOCK_TIME);
523
524 gst_element_class_set_static_metadata (element_class, "AppSink",
525 "Generic/Sink", "Allow the application to get access to raw buffer",
526 "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com>");
527
528 gst_element_class_add_static_pad_template (element_class,
529 &gst_app_sink_template);
530
531 basesink_class->unlock = gst_app_sink_unlock_start;
532 basesink_class->unlock_stop = gst_app_sink_unlock_stop;
533 basesink_class->start = gst_app_sink_start;
534 basesink_class->stop = gst_app_sink_stop;
535 basesink_class->event = gst_app_sink_event;
536 basesink_class->preroll = gst_app_sink_preroll;
537 basesink_class->render = gst_app_sink_render;
538 basesink_class->render_list = gst_app_sink_render_list;
539 basesink_class->get_caps = gst_app_sink_getcaps;
540 basesink_class->set_caps = gst_app_sink_setcaps;
541 basesink_class->query = gst_app_sink_query;
542
543 klass->pull_preroll = gst_app_sink_pull_preroll;
544 klass->pull_sample = gst_app_sink_pull_sample;
545 klass->try_pull_preroll = gst_app_sink_try_pull_preroll;
546 klass->try_pull_sample = gst_app_sink_try_pull_sample;
547 klass->try_pull_object = gst_app_sink_try_pull_object;
548 }
549
550 static void
gst_app_sink_init(GstAppSink * appsink)551 gst_app_sink_init (GstAppSink * appsink)
552 {
553 GstAppSinkPrivate *priv;
554
555 priv = appsink->priv = gst_app_sink_get_instance_private (appsink);
556
557 g_mutex_init (&priv->mutex);
558 g_cond_init (&priv->cond);
559 priv->queue = gst_queue_array_new (16);
560 priv->sample = gst_sample_new (NULL, NULL, NULL, NULL);
561
562 priv->emit_signals = DEFAULT_PROP_EMIT_SIGNALS;
563 priv->max_buffers = DEFAULT_PROP_MAX_BUFFERS;
564 priv->drop = DEFAULT_PROP_DROP;
565 priv->wait_on_eos = DEFAULT_PROP_WAIT_ON_EOS;
566 priv->buffer_lists_supported = DEFAULT_PROP_BUFFER_LIST;
567 priv->wait_status = NOONE_WAITING;
568 }
569
570 static void
gst_app_sink_dispose(GObject * obj)571 gst_app_sink_dispose (GObject * obj)
572 {
573 GstAppSink *appsink = GST_APP_SINK_CAST (obj);
574 GstAppSinkPrivate *priv = appsink->priv;
575 GstMiniObject *queue_obj;
576 Callbacks *callbacks = NULL;
577
578 GST_OBJECT_LOCK (appsink);
579 if (priv->caps) {
580 gst_caps_unref (priv->caps);
581 priv->caps = NULL;
582 }
583 GST_OBJECT_UNLOCK (appsink);
584
585 g_mutex_lock (&priv->mutex);
586 if (priv->callbacks)
587 callbacks = g_steal_pointer (&priv->callbacks);
588 while ((queue_obj = gst_queue_array_pop_head (priv->queue)))
589 gst_mini_object_unref (queue_obj);
590 gst_buffer_replace (&priv->preroll_buffer, NULL);
591 gst_caps_replace (&priv->preroll_caps, NULL);
592 gst_caps_replace (&priv->last_caps, NULL);
593 if (priv->sample) {
594 gst_sample_unref (priv->sample);
595 priv->sample = NULL;
596 }
597 g_mutex_unlock (&priv->mutex);
598
599 g_clear_pointer (&callbacks, callbacks_unref);
600
601 G_OBJECT_CLASS (parent_class)->dispose (obj);
602 }
603
604 static void
gst_app_sink_finalize(GObject * obj)605 gst_app_sink_finalize (GObject * obj)
606 {
607 GstAppSink *appsink = GST_APP_SINK_CAST (obj);
608 GstAppSinkPrivate *priv = appsink->priv;
609
610 g_mutex_clear (&priv->mutex);
611 g_cond_clear (&priv->cond);
612 gst_queue_array_free (priv->queue);
613
614 G_OBJECT_CLASS (parent_class)->finalize (obj);
615 }
616
617 static void
gst_app_sink_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)618 gst_app_sink_set_property (GObject * object, guint prop_id,
619 const GValue * value, GParamSpec * pspec)
620 {
621 GstAppSink *appsink = GST_APP_SINK_CAST (object);
622
623 switch (prop_id) {
624 case PROP_CAPS:
625 gst_app_sink_set_caps (appsink, gst_value_get_caps (value));
626 break;
627 case PROP_EMIT_SIGNALS:
628 gst_app_sink_set_emit_signals (appsink, g_value_get_boolean (value));
629 break;
630 case PROP_MAX_BUFFERS:
631 gst_app_sink_set_max_buffers (appsink, g_value_get_uint (value));
632 break;
633 case PROP_DROP:
634 gst_app_sink_set_drop (appsink, g_value_get_boolean (value));
635 break;
636 case PROP_BUFFER_LIST:
637 gst_app_sink_set_buffer_list_support (appsink,
638 g_value_get_boolean (value));
639 break;
640 case PROP_WAIT_ON_EOS:
641 gst_app_sink_set_wait_on_eos (appsink, g_value_get_boolean (value));
642 break;
643 default:
644 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
645 break;
646 }
647 }
648
649 static void
gst_app_sink_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)650 gst_app_sink_get_property (GObject * object, guint prop_id, GValue * value,
651 GParamSpec * pspec)
652 {
653 GstAppSink *appsink = GST_APP_SINK_CAST (object);
654
655 switch (prop_id) {
656 case PROP_CAPS:
657 {
658 GstCaps *caps;
659
660 caps = gst_app_sink_get_caps (appsink);
661 gst_value_set_caps (value, caps);
662 if (caps)
663 gst_caps_unref (caps);
664 break;
665 }
666 case PROP_EOS:
667 g_value_set_boolean (value, gst_app_sink_is_eos (appsink));
668 break;
669 case PROP_EMIT_SIGNALS:
670 g_value_set_boolean (value, gst_app_sink_get_emit_signals (appsink));
671 break;
672 case PROP_MAX_BUFFERS:
673 g_value_set_uint (value, gst_app_sink_get_max_buffers (appsink));
674 break;
675 case PROP_DROP:
676 g_value_set_boolean (value, gst_app_sink_get_drop (appsink));
677 break;
678 case PROP_BUFFER_LIST:
679 g_value_set_boolean (value,
680 gst_app_sink_get_buffer_list_support (appsink));
681 break;
682 case PROP_WAIT_ON_EOS:
683 g_value_set_boolean (value, gst_app_sink_get_wait_on_eos (appsink));
684 break;
685 default:
686 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
687 break;
688 }
689 }
690
691 static gboolean
gst_app_sink_unlock_start(GstBaseSink * bsink)692 gst_app_sink_unlock_start (GstBaseSink * bsink)
693 {
694 GstAppSink *appsink = GST_APP_SINK_CAST (bsink);
695 GstAppSinkPrivate *priv = appsink->priv;
696
697 g_mutex_lock (&priv->mutex);
698 GST_DEBUG_OBJECT (appsink, "unlock start");
699 priv->unlock = TRUE;
700 g_cond_signal (&priv->cond);
701 g_mutex_unlock (&priv->mutex);
702
703 return TRUE;
704 }
705
706 static gboolean
gst_app_sink_unlock_stop(GstBaseSink * bsink)707 gst_app_sink_unlock_stop (GstBaseSink * bsink)
708 {
709 GstAppSink *appsink = GST_APP_SINK_CAST (bsink);
710 GstAppSinkPrivate *priv = appsink->priv;
711
712 g_mutex_lock (&priv->mutex);
713 GST_DEBUG_OBJECT (appsink, "unlock stop");
714 priv->unlock = FALSE;
715 g_cond_signal (&priv->cond);
716 g_mutex_unlock (&priv->mutex);
717
718 return TRUE;
719 }
720
721 static void
gst_app_sink_flush_unlocked(GstAppSink * appsink)722 gst_app_sink_flush_unlocked (GstAppSink * appsink)
723 {
724 GstMiniObject *obj;
725 GstAppSinkPrivate *priv = appsink->priv;
726
727 GST_DEBUG_OBJECT (appsink, "flush stop appsink");
728 priv->is_eos = FALSE;
729 gst_buffer_replace (&priv->preroll_buffer, NULL);
730 while ((obj = gst_queue_array_pop_head (priv->queue)))
731 gst_mini_object_unref (obj);
732 priv->num_buffers = 0;
733 priv->num_events = 0;
734 gst_caps_replace (&priv->last_caps, NULL);
735 g_cond_signal (&priv->cond);
736 }
737
738 static gboolean
gst_app_sink_start(GstBaseSink * psink)739 gst_app_sink_start (GstBaseSink * psink)
740 {
741 GstAppSink *appsink = GST_APP_SINK_CAST (psink);
742 GstAppSinkPrivate *priv = appsink->priv;
743
744 g_mutex_lock (&priv->mutex);
745 GST_DEBUG_OBJECT (appsink, "starting");
746 priv->wait_status = NOONE_WAITING;
747 priv->flushing = FALSE;
748 priv->started = TRUE;
749 gst_segment_init (&priv->preroll_segment, GST_FORMAT_TIME);
750 gst_segment_init (&priv->last_segment, GST_FORMAT_TIME);
751 priv->sample = gst_sample_make_writable (priv->sample);
752 gst_sample_set_buffer (priv->sample, NULL);
753 gst_sample_set_buffer_list (priv->sample, NULL);
754 gst_sample_set_caps (priv->sample, NULL);
755 gst_sample_set_segment (priv->sample, NULL);
756 g_mutex_unlock (&priv->mutex);
757
758 return TRUE;
759 }
760
761 static gboolean
gst_app_sink_stop(GstBaseSink * psink)762 gst_app_sink_stop (GstBaseSink * psink)
763 {
764 GstAppSink *appsink = GST_APP_SINK_CAST (psink);
765 GstAppSinkPrivate *priv = appsink->priv;
766
767 g_mutex_lock (&priv->mutex);
768 GST_DEBUG_OBJECT (appsink, "stopping");
769 priv->flushing = TRUE;
770 priv->started = FALSE;
771 priv->wait_status = NOONE_WAITING;
772 gst_app_sink_flush_unlocked (appsink);
773 gst_buffer_replace (&priv->preroll_buffer, NULL);
774 gst_caps_replace (&priv->preroll_caps, NULL);
775 gst_caps_replace (&priv->last_caps, NULL);
776 gst_segment_init (&priv->preroll_segment, GST_FORMAT_UNDEFINED);
777 gst_segment_init (&priv->last_segment, GST_FORMAT_UNDEFINED);
778 g_mutex_unlock (&priv->mutex);
779
780 return TRUE;
781 }
782
783 static gboolean
gst_app_sink_setcaps(GstBaseSink * sink,GstCaps * caps)784 gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps)
785 {
786 GstAppSink *appsink = GST_APP_SINK_CAST (sink);
787 GstAppSinkPrivate *priv = appsink->priv;
788
789 g_mutex_lock (&priv->mutex);
790 GST_DEBUG_OBJECT (appsink, "receiving CAPS");
791 gst_queue_array_push_tail (priv->queue, gst_event_new_caps (caps));
792 priv->num_events++;
793 if (!priv->preroll_buffer)
794 gst_caps_replace (&priv->preroll_caps, caps);
795 g_mutex_unlock (&priv->mutex);
796
797 return TRUE;
798 }
799
800 static gboolean
gst_app_sink_event(GstBaseSink * sink,GstEvent * event)801 gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
802 {
803 GstAppSink *appsink = GST_APP_SINK_CAST (sink);
804 GstAppSinkPrivate *priv = appsink->priv;
805
806 GST_DEBUG_OBJECT (appsink, "%" GST_PTR_FORMAT, event);
807
808 switch (event->type) {
809 case GST_EVENT_SEGMENT:
810 g_mutex_lock (&priv->mutex);
811 GST_DEBUG_OBJECT (appsink, "receiving SEGMENT");
812 if (!priv->preroll_buffer)
813 gst_event_copy_segment (event, &priv->preroll_segment);
814 g_mutex_unlock (&priv->mutex);
815 break;
816 case GST_EVENT_EOS:{
817 gboolean emit = TRUE;
818 Callbacks *callbacks = NULL;
819
820 g_mutex_lock (&priv->mutex);
821 GST_DEBUG_OBJECT (appsink, "receiving EOS");
822 priv->is_eos = TRUE;
823 g_cond_signal (&priv->cond);
824 g_mutex_unlock (&priv->mutex);
825
826 g_mutex_lock (&priv->mutex);
827 /* wait until all buffers are consumed or we're flushing.
828 * Otherwise we might signal EOS before all buffers are
829 * consumed, which is a bit confusing for the application
830 */
831 while (priv->num_buffers > 0 && !priv->flushing && priv->wait_on_eos) {
832 if (priv->unlock) {
833 /* we are asked to unlock, call the wait_preroll method */
834 g_mutex_unlock (&priv->mutex);
835 if (gst_base_sink_wait_preroll (sink) != GST_FLOW_OK) {
836 /* Directly go out of here */
837 gst_event_unref (event);
838 return FALSE;
839 }
840
841 /* we are allowed to continue now */
842 g_mutex_lock (&priv->mutex);
843 continue;
844 }
845
846 priv->wait_status |= STREAM_WAITING;
847 g_cond_wait (&priv->cond, &priv->mutex);
848 priv->wait_status &= ~STREAM_WAITING;
849 }
850 if (priv->flushing)
851 emit = FALSE;
852
853 if (emit && priv->callbacks)
854 callbacks = callbacks_ref (priv->callbacks);
855 g_mutex_unlock (&priv->mutex);
856
857 if (emit) {
858 /* emit EOS now */
859 if (callbacks && callbacks->callbacks.eos)
860 callbacks->callbacks.eos (appsink, callbacks->user_data);
861 else
862 g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_EOS], 0);
863
864 g_clear_pointer (&callbacks, callbacks_unref);
865 }
866
867 break;
868 }
869 case GST_EVENT_FLUSH_START:
870 /* we don't have to do anything here, the base class will call unlock
871 * which will make sure we exit the _render method */
872 GST_DEBUG_OBJECT (appsink, "received FLUSH_START");
873 break;
874 case GST_EVENT_FLUSH_STOP:
875 g_mutex_lock (&priv->mutex);
876 GST_DEBUG_OBJECT (appsink, "received FLUSH_STOP");
877 gst_app_sink_flush_unlocked (appsink);
878 g_mutex_unlock (&priv->mutex);
879 break;
880 default:
881 break;
882 }
883
884 if (GST_EVENT_TYPE (event) != GST_EVENT_EOS
885 && GST_EVENT_IS_SERIALIZED (event)) {
886 gboolean emit;
887 Callbacks *callbacks = NULL;
888 gboolean ret;
889
890 g_mutex_lock (&priv->mutex);
891
892 emit = priv->emit_signals;
893 if (priv->callbacks)
894 callbacks = callbacks_ref (priv->callbacks);
895
896 gst_queue_array_push_tail (priv->queue, gst_event_ref (event));
897 priv->num_events++;
898
899 g_mutex_unlock (&priv->mutex);
900
901 if (callbacks && callbacks->callbacks.new_event) {
902 ret = callbacks->callbacks.new_event (appsink, callbacks->user_data);
903 } else {
904 ret = FALSE;
905 if (emit)
906 g_signal_emit (appsink,
907 gst_app_sink_signals[SIGNAL_NEW_SERIALIZED_EVENT], 0, &ret);
908 }
909 g_clear_pointer (&callbacks, callbacks_unref);
910
911 if (ret) {
912 gst_event_unref (event);
913 return TRUE;
914 }
915 }
916
917 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
918 }
919
920 static GstFlowReturn
gst_app_sink_preroll(GstBaseSink * psink,GstBuffer * buffer)921 gst_app_sink_preroll (GstBaseSink * psink, GstBuffer * buffer)
922 {
923 GstFlowReturn res;
924 GstAppSink *appsink = GST_APP_SINK_CAST (psink);
925 GstAppSinkPrivate *priv = appsink->priv;
926 gboolean emit;
927 Callbacks *callbacks = NULL;
928
929 g_mutex_lock (&priv->mutex);
930 if (priv->flushing)
931 goto flushing;
932
933 GST_DEBUG_OBJECT (appsink, "setting preroll buffer %p", buffer);
934 gst_buffer_replace (&priv->preroll_buffer, buffer);
935
936 if ((priv->wait_status & APP_WAITING))
937 g_cond_signal (&priv->cond);
938
939 emit = priv->emit_signals;
940 if (priv->callbacks)
941 callbacks = callbacks_ref (priv->callbacks);
942 g_mutex_unlock (&priv->mutex);
943
944 if (callbacks && callbacks->callbacks.new_preroll) {
945 res = callbacks->callbacks.new_preroll (appsink, callbacks->user_data);
946 } else {
947 res = GST_FLOW_OK;
948 if (emit)
949 g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_PREROLL], 0,
950 &res);
951 }
952
953 g_clear_pointer (&callbacks, callbacks_unref);
954
955 return res;
956
957 flushing:
958 {
959 GST_DEBUG_OBJECT (appsink, "we are flushing");
960 g_mutex_unlock (&priv->mutex);
961 return GST_FLOW_FLUSHING;
962 }
963 }
964
965 static GstMiniObject *
dequeue_object(GstAppSink * appsink)966 dequeue_object (GstAppSink * appsink)
967 {
968 GstAppSinkPrivate *priv = appsink->priv;
969 GstMiniObject *obj;
970
971 obj = gst_queue_array_pop_head (priv->queue);
972
973 if (GST_IS_BUFFER (obj) || GST_IS_BUFFER_LIST (obj)) {
974 GST_DEBUG_OBJECT (appsink, "dequeued buffer/list %p", obj);
975 priv->num_buffers--;
976 } else if (GST_IS_EVENT (obj)) {
977 GstEvent *event = GST_EVENT_CAST (obj);
978
979 priv->num_events--;
980
981 switch (GST_EVENT_TYPE (obj)) {
982 case GST_EVENT_CAPS:
983 {
984 GstCaps *caps;
985
986 gst_event_parse_caps (event, &caps);
987 GST_DEBUG_OBJECT (appsink, "activating caps %" GST_PTR_FORMAT, caps);
988 gst_caps_replace (&priv->last_caps, caps);
989 priv->sample = gst_sample_make_writable (priv->sample);
990 gst_sample_set_caps (priv->sample, priv->last_caps);
991 break;
992 }
993 case GST_EVENT_SEGMENT:
994 gst_event_copy_segment (event, &priv->last_segment);
995 priv->sample = gst_sample_make_writable (priv->sample);
996 gst_sample_set_segment (priv->sample, &priv->last_segment);
997 GST_DEBUG_OBJECT (appsink, "activated segment %" GST_SEGMENT_FORMAT,
998 &priv->last_segment);
999 break;
1000 default:
1001 break;
1002 }
1003 }
1004
1005 return obj;
1006 }
1007
1008 static GstMiniObject *
dequeue_buffer(GstAppSink * appsink)1009 dequeue_buffer (GstAppSink * appsink)
1010 {
1011 GstMiniObject *obj;
1012
1013 do {
1014 obj = dequeue_object (appsink);
1015
1016 if (GST_IS_BUFFER (obj) || GST_IS_BUFFER_LIST (obj)) {
1017 break;
1018 }
1019
1020 gst_mini_object_unref (obj);
1021 } while (TRUE);
1022
1023 return obj;
1024 }
1025
1026 static GstFlowReturn
gst_app_sink_render_common(GstBaseSink * psink,GstMiniObject * data,gboolean is_list)1027 gst_app_sink_render_common (GstBaseSink * psink, GstMiniObject * data,
1028 gboolean is_list)
1029 {
1030 GstFlowReturn ret;
1031 GstAppSink *appsink = GST_APP_SINK_CAST (psink);
1032 GstAppSinkPrivate *priv = appsink->priv;
1033 gboolean emit;
1034 Callbacks *callbacks = NULL;
1035
1036 restart:
1037 g_mutex_lock (&priv->mutex);
1038 if (priv->flushing)
1039 goto flushing;
1040
1041 /* queue holding caps event might have been FLUSHed,
1042 * but caps state still present in pad caps */
1043 if (G_UNLIKELY (!priv->last_caps &&
1044 gst_pad_has_current_caps (GST_BASE_SINK_PAD (psink)))) {
1045 priv->last_caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (psink));
1046 gst_sample_set_caps (priv->sample, priv->last_caps);
1047 GST_DEBUG_OBJECT (appsink, "activating pad caps %" GST_PTR_FORMAT,
1048 priv->last_caps);
1049 }
1050
1051 GST_DEBUG_OBJECT (appsink, "pushing render buffer/list %p on queue (%d)",
1052 data, priv->num_buffers);
1053
1054 while (priv->max_buffers > 0 && priv->num_buffers >= priv->max_buffers) {
1055 if (priv->drop) {
1056 GstMiniObject *old;
1057
1058 /* we need to drop the oldest buffer/list and try again */
1059 if ((old = dequeue_buffer (appsink))) {
1060 GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", old);
1061 gst_mini_object_unref (old);
1062 }
1063 } else {
1064 GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
1065 priv->num_buffers, priv->max_buffers);
1066
1067 if (priv->unlock) {
1068 /* we are asked to unlock, call the wait_preroll method */
1069 g_mutex_unlock (&priv->mutex);
1070 if ((ret = gst_base_sink_wait_preroll (psink)) != GST_FLOW_OK)
1071 goto stopping;
1072
1073 /* we are allowed to continue now */
1074 goto restart;
1075 }
1076
1077 /* wait for a buffer to be removed or flush */
1078 priv->wait_status |= STREAM_WAITING;
1079 g_cond_wait (&priv->cond, &priv->mutex);
1080 priv->wait_status &= ~STREAM_WAITING;
1081
1082 if (priv->flushing)
1083 goto flushing;
1084 }
1085 }
1086 /* we need to ref the buffer/list when pushing it in the queue */
1087 gst_queue_array_push_tail (priv->queue, gst_mini_object_ref (data));
1088 priv->num_buffers++;
1089
1090 if ((priv->wait_status & APP_WAITING))
1091 g_cond_signal (&priv->cond);
1092
1093 emit = priv->emit_signals;
1094 if (priv->callbacks)
1095 callbacks = callbacks_ref (priv->callbacks);
1096 g_mutex_unlock (&priv->mutex);
1097
1098 if (callbacks && callbacks->callbacks.new_sample) {
1099 ret = callbacks->callbacks.new_sample (appsink, callbacks->user_data);
1100 } else {
1101 ret = GST_FLOW_OK;
1102 if (emit)
1103 g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_SAMPLE], 0, &ret);
1104 }
1105 g_clear_pointer (&callbacks, callbacks_unref);
1106
1107 return ret;
1108
1109 flushing:
1110 {
1111 GST_DEBUG_OBJECT (appsink, "we are flushing");
1112 g_mutex_unlock (&priv->mutex);
1113 return GST_FLOW_FLUSHING;
1114 }
1115 stopping:
1116 {
1117 GST_DEBUG_OBJECT (appsink, "we are stopping");
1118 return ret;
1119 }
1120 }
1121
1122 static GstFlowReturn
gst_app_sink_render(GstBaseSink * psink,GstBuffer * buffer)1123 gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
1124 {
1125 return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (buffer),
1126 FALSE);
1127 }
1128
1129 static GstFlowReturn
gst_app_sink_render_list(GstBaseSink * sink,GstBufferList * list)1130 gst_app_sink_render_list (GstBaseSink * sink, GstBufferList * list)
1131 {
1132 GstFlowReturn flow;
1133 GstAppSink *appsink;
1134 GstBuffer *buffer;
1135 guint i, len;
1136
1137 appsink = GST_APP_SINK_CAST (sink);
1138
1139 if (appsink->priv->buffer_lists_supported)
1140 return gst_app_sink_render_common (sink, GST_MINI_OBJECT_CAST (list), TRUE);
1141
1142 /* The application doesn't support buffer lists, extract individual buffers
1143 * then and push them one-by-one */
1144 GST_INFO_OBJECT (sink, "chaining each group in list as a merged buffer");
1145
1146 len = gst_buffer_list_length (list);
1147
1148 flow = GST_FLOW_OK;
1149 for (i = 0; i < len; i++) {
1150 buffer = gst_buffer_list_get (list, i);
1151 flow = gst_app_sink_render (sink, buffer);
1152 if (flow != GST_FLOW_OK)
1153 break;
1154 }
1155
1156 return flow;
1157 }
1158
1159 static GstCaps *
gst_app_sink_getcaps(GstBaseSink * psink,GstCaps * filter)1160 gst_app_sink_getcaps (GstBaseSink * psink, GstCaps * filter)
1161 {
1162 GstCaps *caps;
1163 GstAppSink *appsink = GST_APP_SINK_CAST (psink);
1164 GstAppSinkPrivate *priv = appsink->priv;
1165
1166 GST_OBJECT_LOCK (appsink);
1167 if ((caps = priv->caps)) {
1168 if (filter)
1169 caps = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
1170 else
1171 gst_caps_ref (caps);
1172 }
1173 GST_DEBUG_OBJECT (appsink, "got caps %" GST_PTR_FORMAT, caps);
1174 GST_OBJECT_UNLOCK (appsink);
1175
1176 return caps;
1177 }
1178
1179 static gboolean
gst_app_sink_query(GstBaseSink * bsink,GstQuery * query)1180 gst_app_sink_query (GstBaseSink * bsink, GstQuery * query)
1181 {
1182 GstAppSink *appsink = GST_APP_SINK_CAST (bsink);
1183 GstAppSinkPrivate *priv = appsink->priv;
1184 gboolean ret;
1185
1186 switch (GST_QUERY_TYPE (query)) {
1187 case GST_QUERY_DRAIN:
1188 {
1189 g_mutex_lock (&priv->mutex);
1190 GST_DEBUG_OBJECT (appsink, "waiting buffers to be consumed");
1191 while (priv->num_buffers > 0 || priv->preroll_buffer) {
1192 if (priv->unlock) {
1193 /* we are asked to unlock, call the wait_preroll method */
1194 g_mutex_unlock (&priv->mutex);
1195 if (gst_base_sink_wait_preroll (bsink) != GST_FLOW_OK) {
1196 /* Directly go out of here */
1197 return FALSE;
1198 }
1199
1200 /* we are allowed to continue now */
1201 g_mutex_lock (&priv->mutex);
1202 continue;
1203 }
1204
1205 priv->wait_status |= STREAM_WAITING;
1206 g_cond_wait (&priv->cond, &priv->mutex);
1207 priv->wait_status &= ~STREAM_WAITING;
1208
1209 if (priv->flushing)
1210 break;
1211 }
1212 g_mutex_unlock (&priv->mutex);
1213 ret = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
1214 break;
1215 }
1216 case GST_QUERY_SEEKING:{
1217 GstFormat fmt;
1218
1219 /* we don't supporting seeking */
1220 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1221 gst_query_set_seeking (query, fmt, FALSE, 0, -1);
1222 ret = TRUE;
1223 break;
1224 }
1225
1226 default:
1227 ret = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
1228 break;
1229 }
1230
1231 return ret;
1232 }
1233
1234 /* external API */
1235
1236 /**
1237 * gst_app_sink_set_caps:
1238 * @appsink: a #GstAppSink
1239 * @caps: (nullable): caps to set
1240 *
1241 * Set the capabilities on the appsink element. This function takes
1242 * a copy of the caps structure. After calling this method, the sink will only
1243 * accept caps that match @caps. If @caps is non-fixed, or incomplete,
1244 * you must check the caps on the samples to get the actual used caps.
1245 */
1246 void
gst_app_sink_set_caps(GstAppSink * appsink,const GstCaps * caps)1247 gst_app_sink_set_caps (GstAppSink * appsink, const GstCaps * caps)
1248 {
1249 GstCaps *old;
1250 GstAppSinkPrivate *priv;
1251
1252 g_return_if_fail (GST_IS_APP_SINK (appsink));
1253
1254 priv = appsink->priv;
1255
1256 GST_OBJECT_LOCK (appsink);
1257 GST_DEBUG_OBJECT (appsink, "setting caps to %" GST_PTR_FORMAT, caps);
1258 if ((old = priv->caps) != caps) {
1259 if (caps)
1260 priv->caps = gst_caps_copy (caps);
1261 else
1262 priv->caps = NULL;
1263 if (old)
1264 gst_caps_unref (old);
1265 }
1266 GST_OBJECT_UNLOCK (appsink);
1267 }
1268
1269 /**
1270 * gst_app_sink_get_caps:
1271 * @appsink: a #GstAppSink
1272 *
1273 * Get the configured caps on @appsink.
1274 *
1275 * Returns: the #GstCaps accepted by the sink. gst_caps_unref() after usage.
1276 */
1277 GstCaps *
gst_app_sink_get_caps(GstAppSink * appsink)1278 gst_app_sink_get_caps (GstAppSink * appsink)
1279 {
1280 GstCaps *caps;
1281 GstAppSinkPrivate *priv;
1282
1283 g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
1284
1285 priv = appsink->priv;
1286
1287 GST_OBJECT_LOCK (appsink);
1288 if ((caps = priv->caps))
1289 gst_caps_ref (caps);
1290 GST_DEBUG_OBJECT (appsink, "getting caps of %" GST_PTR_FORMAT, caps);
1291 GST_OBJECT_UNLOCK (appsink);
1292
1293 return caps;
1294 }
1295
1296 /**
1297 * gst_app_sink_is_eos:
1298 * @appsink: a #GstAppSink
1299 *
1300 * Check if @appsink is EOS, which is when no more samples can be pulled because
1301 * an EOS event was received.
1302 *
1303 * This function also returns %TRUE when the appsink is not in the PAUSED or
1304 * PLAYING state.
1305 *
1306 * Returns: %TRUE if no more samples can be pulled and the appsink is EOS.
1307 */
1308 gboolean
gst_app_sink_is_eos(GstAppSink * appsink)1309 gst_app_sink_is_eos (GstAppSink * appsink)
1310 {
1311 gboolean ret;
1312 GstAppSinkPrivate *priv;
1313
1314 g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1315
1316 priv = appsink->priv;
1317
1318 g_mutex_lock (&priv->mutex);
1319 if (!priv->started)
1320 goto not_started;
1321
1322 if (priv->is_eos && priv->num_buffers == 0) {
1323 GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty");
1324 ret = TRUE;
1325 } else {
1326 GST_DEBUG_OBJECT (appsink, "we are not yet EOS");
1327 ret = FALSE;
1328 }
1329 g_mutex_unlock (&priv->mutex);
1330
1331 return ret;
1332
1333 not_started:
1334 {
1335 GST_DEBUG_OBJECT (appsink, "we are stopped, return TRUE");
1336 g_mutex_unlock (&priv->mutex);
1337 return TRUE;
1338 }
1339 }
1340
1341 /**
1342 * gst_app_sink_set_emit_signals:
1343 * @appsink: a #GstAppSink
1344 * @emit: the new state
1345 *
1346 * Make appsink emit the "new-preroll" and "new-sample" signals. This option is
1347 * by default disabled because signal emission is expensive and unneeded when
1348 * the application prefers to operate in pull mode.
1349 */
1350 void
gst_app_sink_set_emit_signals(GstAppSink * appsink,gboolean emit)1351 gst_app_sink_set_emit_signals (GstAppSink * appsink, gboolean emit)
1352 {
1353 GstAppSinkPrivate *priv;
1354
1355 g_return_if_fail (GST_IS_APP_SINK (appsink));
1356
1357 priv = appsink->priv;
1358
1359 g_mutex_lock (&priv->mutex);
1360 priv->emit_signals = emit;
1361 g_mutex_unlock (&priv->mutex);
1362 }
1363
1364 /**
1365 * gst_app_sink_get_emit_signals:
1366 * @appsink: a #GstAppSink
1367 *
1368 * Check if appsink will emit the "new-preroll" and "new-sample" signals.
1369 *
1370 * Returns: %TRUE if @appsink is emitting the "new-preroll" and "new-sample"
1371 * signals.
1372 */
1373 gboolean
gst_app_sink_get_emit_signals(GstAppSink * appsink)1374 gst_app_sink_get_emit_signals (GstAppSink * appsink)
1375 {
1376 gboolean result;
1377 GstAppSinkPrivate *priv;
1378
1379 g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1380
1381 priv = appsink->priv;
1382
1383 g_mutex_lock (&priv->mutex);
1384 result = priv->emit_signals;
1385 g_mutex_unlock (&priv->mutex);
1386
1387 return result;
1388 }
1389
1390 /**
1391 * gst_app_sink_set_max_buffers:
1392 * @appsink: a #GstAppSink
1393 * @max: the maximum number of buffers to queue
1394 *
1395 * Set the maximum amount of buffers that can be queued in @appsink. After this
1396 * amount of buffers are queued in appsink, any more buffers will block upstream
1397 * elements until a sample is pulled from @appsink.
1398 */
1399 void
gst_app_sink_set_max_buffers(GstAppSink * appsink,guint max)1400 gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max)
1401 {
1402 GstAppSinkPrivate *priv;
1403
1404 g_return_if_fail (GST_IS_APP_SINK (appsink));
1405
1406 priv = appsink->priv;
1407
1408 g_mutex_lock (&priv->mutex);
1409 if (max != priv->max_buffers) {
1410 priv->max_buffers = max;
1411 /* signal the change */
1412 g_cond_signal (&priv->cond);
1413 }
1414 g_mutex_unlock (&priv->mutex);
1415 }
1416
1417 /**
1418 * gst_app_sink_get_max_buffers:
1419 * @appsink: a #GstAppSink
1420 *
1421 * Get the maximum amount of buffers that can be queued in @appsink.
1422 *
1423 * Returns: The maximum amount of buffers that can be queued.
1424 */
1425 guint
gst_app_sink_get_max_buffers(GstAppSink * appsink)1426 gst_app_sink_get_max_buffers (GstAppSink * appsink)
1427 {
1428 guint result;
1429 GstAppSinkPrivate *priv;
1430
1431 g_return_val_if_fail (GST_IS_APP_SINK (appsink), 0);
1432
1433 priv = appsink->priv;
1434
1435 g_mutex_lock (&priv->mutex);
1436 result = priv->max_buffers;
1437 g_mutex_unlock (&priv->mutex);
1438
1439 return result;
1440 }
1441
1442 /**
1443 * gst_app_sink_set_drop:
1444 * @appsink: a #GstAppSink
1445 * @drop: the new state
1446 *
1447 * Instruct @appsink to drop old buffers when the maximum amount of queued
1448 * buffers is reached.
1449 */
1450 void
gst_app_sink_set_drop(GstAppSink * appsink,gboolean drop)1451 gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop)
1452 {
1453 GstAppSinkPrivate *priv;
1454
1455 g_return_if_fail (GST_IS_APP_SINK (appsink));
1456
1457 priv = appsink->priv;
1458
1459 g_mutex_lock (&priv->mutex);
1460 if (priv->drop != drop) {
1461 priv->drop = drop;
1462 /* signal the change */
1463 g_cond_signal (&priv->cond);
1464 }
1465 g_mutex_unlock (&priv->mutex);
1466 }
1467
1468 /**
1469 * gst_app_sink_get_drop:
1470 * @appsink: a #GstAppSink
1471 *
1472 * Check if @appsink will drop old buffers when the maximum amount of queued
1473 * buffers is reached.
1474 *
1475 * Returns: %TRUE if @appsink is dropping old buffers when the queue is
1476 * filled.
1477 */
1478 gboolean
gst_app_sink_get_drop(GstAppSink * appsink)1479 gst_app_sink_get_drop (GstAppSink * appsink)
1480 {
1481 gboolean result;
1482 GstAppSinkPrivate *priv;
1483
1484 g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1485
1486 priv = appsink->priv;
1487
1488 g_mutex_lock (&priv->mutex);
1489 result = priv->drop;
1490 g_mutex_unlock (&priv->mutex);
1491
1492 return result;
1493 }
1494
1495 /**
1496 * gst_app_sink_set_buffer_list_support:
1497 * @appsink: a #GstAppSink
1498 * @enable_lists: enable or disable buffer list support
1499 *
1500 * Instruct @appsink to enable or disable buffer list support.
1501 *
1502 * For backwards-compatibility reasons applications need to opt in
1503 * to indicate that they will be able to handle buffer lists.
1504 *
1505 * Since: 1.12
1506 */
1507 void
gst_app_sink_set_buffer_list_support(GstAppSink * appsink,gboolean enable_lists)1508 gst_app_sink_set_buffer_list_support (GstAppSink * appsink,
1509 gboolean enable_lists)
1510 {
1511 GstAppSinkPrivate *priv;
1512
1513 g_return_if_fail (GST_IS_APP_SINK (appsink));
1514
1515 priv = appsink->priv;
1516
1517 g_mutex_lock (&priv->mutex);
1518 if (priv->buffer_lists_supported != enable_lists) {
1519 priv->buffer_lists_supported = enable_lists;
1520 }
1521 g_mutex_unlock (&priv->mutex);
1522 }
1523
1524 /**
1525 * gst_app_sink_get_buffer_list_support:
1526 * @appsink: a #GstAppSink
1527 *
1528 * Check if @appsink supports buffer lists.
1529 *
1530 * Returns: %TRUE if @appsink supports buffer lists.
1531 *
1532 * Since: 1.12
1533 */
1534 gboolean
gst_app_sink_get_buffer_list_support(GstAppSink * appsink)1535 gst_app_sink_get_buffer_list_support (GstAppSink * appsink)
1536 {
1537 gboolean result;
1538 GstAppSinkPrivate *priv;
1539
1540 g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1541
1542 priv = appsink->priv;
1543
1544 g_mutex_lock (&priv->mutex);
1545 result = priv->buffer_lists_supported;
1546 g_mutex_unlock (&priv->mutex);
1547
1548 return result;
1549 }
1550
1551 /**
1552 * gst_app_sink_set_wait_on_eos:
1553 * @appsink: a #GstAppSink
1554 * @wait: the new state
1555 *
1556 * Instruct @appsink to wait for all buffers to be consumed when an EOS is received.
1557 *
1558 */
1559 void
gst_app_sink_set_wait_on_eos(GstAppSink * appsink,gboolean wait)1560 gst_app_sink_set_wait_on_eos (GstAppSink * appsink, gboolean wait)
1561 {
1562 GstAppSinkPrivate *priv;
1563
1564 g_return_if_fail (GST_IS_APP_SINK (appsink));
1565
1566 priv = appsink->priv;
1567
1568 g_mutex_lock (&priv->mutex);
1569 if (priv->wait_on_eos != wait) {
1570 priv->wait_on_eos = wait;
1571 /* signal the change */
1572 g_cond_signal (&priv->cond);
1573 }
1574 g_mutex_unlock (&priv->mutex);
1575 }
1576
1577 /**
1578 * gst_app_sink_get_wait_on_eos:
1579 * @appsink: a #GstAppSink
1580 *
1581 * Check if @appsink will wait for all buffers to be consumed when an EOS is
1582 * received.
1583 *
1584 * Returns: %TRUE if @appsink will wait for all buffers to be consumed when an
1585 * EOS is received.
1586 */
1587 gboolean
gst_app_sink_get_wait_on_eos(GstAppSink * appsink)1588 gst_app_sink_get_wait_on_eos (GstAppSink * appsink)
1589 {
1590 gboolean result;
1591 GstAppSinkPrivate *priv;
1592
1593 g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1594
1595 priv = appsink->priv;
1596
1597 g_mutex_lock (&priv->mutex);
1598 result = priv->wait_on_eos;
1599 g_mutex_unlock (&priv->mutex);
1600
1601 return result;
1602 }
1603
1604 /**
1605 * gst_app_sink_pull_preroll:
1606 * @appsink: a #GstAppSink
1607 *
1608 * Get the last preroll sample in @appsink. This was the sample that caused the
1609 * appsink to preroll in the PAUSED state.
1610 *
1611 * This function is typically used when dealing with a pipeline in the PAUSED
1612 * state. Calling this function after doing a seek will give the sample right
1613 * after the seek position.
1614 *
1615 * Calling this function will clear the internal reference to the preroll
1616 * buffer.
1617 *
1618 * Note that the preroll sample will also be returned as the first sample
1619 * when calling gst_app_sink_pull_sample().
1620 *
1621 * If an EOS event was received before any buffers, this function returns
1622 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
1623 *
1624 * This function blocks until a preroll sample or EOS is received or the appsink
1625 * element is set to the READY/NULL state.
1626 *
1627 * Returns: (transfer full) (nullable): a #GstSample or NULL when the appsink is stopped or EOS.
1628 * Call gst_sample_unref() after usage.
1629 */
1630 GstSample *
gst_app_sink_pull_preroll(GstAppSink * appsink)1631 gst_app_sink_pull_preroll (GstAppSink * appsink)
1632 {
1633 return gst_app_sink_try_pull_preroll (appsink, GST_CLOCK_TIME_NONE);
1634 }
1635
1636 /**
1637 * gst_app_sink_pull_sample:
1638 * @appsink: a #GstAppSink
1639 *
1640 * This function blocks until a sample or EOS becomes available or the appsink
1641 * element is set to the READY/NULL state.
1642 *
1643 * This function will only return samples when the appsink is in the PLAYING
1644 * state. All rendered buffers will be put in a queue so that the application
1645 * can pull samples at its own rate. Note that when the application does not
1646 * pull samples fast enough, the queued buffers could consume a lot of memory,
1647 * especially when dealing with raw video frames.
1648 *
1649 * If an EOS event was received before any buffers, this function returns
1650 * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
1651 *
1652 * Returns: (transfer full) (nullable): a #GstSample or NULL when the appsink is stopped or EOS.
1653 * Call gst_sample_unref() after usage.
1654 */
1655 GstSample *
gst_app_sink_pull_sample(GstAppSink * appsink)1656 gst_app_sink_pull_sample (GstAppSink * appsink)
1657 {
1658 return gst_app_sink_try_pull_sample (appsink, GST_CLOCK_TIME_NONE);
1659 }
1660
1661 /**
1662 * gst_app_sink_pull_object: (skip)
1663 * @appsink: a #GstAppSink
1664 *
1665 * This function blocks until a sample or an event becomes available or the appsink
1666 * element is set to the READY/NULL state.
1667 *
1668 * This function will only return samples when the appsink is in the PLAYING
1669 * state. All rendered buffers and events will be put in a queue so that the application
1670 * can pull them at its own rate. Note that when the application does not
1671 * pull samples fast enough, the queued buffers could consume a lot of memory,
1672 * especially when dealing with raw video frames.
1673 * Events can be pulled when the appsink is in the READY, PAUSED or PLAYING state.
1674 *
1675 * This function will only pull serialized events, excluding
1676 * the EOS event for which this functions returns
1677 * %NULL. Use gst_app_sink_is_eos() to check for the EOS condition.
1678 *
1679 * This method is a variant of gst_app_sink_pull_sample() that can be used
1680 * to handle incoming events events as well as samples.
1681 *
1682 * Note that future releases may extend this API to return other object types
1683 * so make sure that your code is checking for the actual type it is handling.
1684 *
1685 * Returns: (transfer full): a #GstSample, or a #GstEvent or NULL when the appsink is stopped or EOS.
1686 * Call gst_mini_object_unref() after usage.
1687 *
1688 * Since: 1.20
1689 */
1690 GstMiniObject *
gst_app_sink_pull_object(GstAppSink * appsink)1691 gst_app_sink_pull_object (GstAppSink * appsink)
1692 {
1693 return gst_app_sink_try_pull_object (appsink, GST_CLOCK_TIME_NONE);
1694 }
1695
1696 /**
1697 * gst_app_sink_try_pull_preroll:
1698 * @appsink: a #GstAppSink
1699 * @timeout: the maximum amount of time to wait for the preroll sample
1700 *
1701 * Get the last preroll sample in @appsink. This was the sample that caused the
1702 * appsink to preroll in the PAUSED state.
1703 *
1704 * This function is typically used when dealing with a pipeline in the PAUSED
1705 * state. Calling this function after doing a seek will give the sample right
1706 * after the seek position.
1707 *
1708 * Calling this function will clear the internal reference to the preroll
1709 * buffer.
1710 *
1711 * Note that the preroll sample will also be returned as the first sample
1712 * when calling gst_app_sink_pull_sample().
1713 *
1714 * If an EOS event was received before any buffers or the timeout expires,
1715 * this function returns %NULL. Use gst_app_sink_is_eos () to check for the EOS
1716 * condition.
1717 *
1718 * This function blocks until a preroll sample or EOS is received, the appsink
1719 * element is set to the READY/NULL state, or the timeout expires.
1720 *
1721 * Returns: (transfer full) (nullable): a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires.
1722 * Call gst_sample_unref() after usage.
1723 *
1724 * Since: 1.10
1725 */
1726 GstSample *
gst_app_sink_try_pull_preroll(GstAppSink * appsink,GstClockTime timeout)1727 gst_app_sink_try_pull_preroll (GstAppSink * appsink, GstClockTime timeout)
1728 {
1729 GstAppSinkPrivate *priv;
1730 GstSample *sample = NULL;
1731 gboolean timeout_valid;
1732 gint64 end_time;
1733
1734 g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
1735
1736 priv = appsink->priv;
1737
1738 timeout_valid = GST_CLOCK_TIME_IS_VALID (timeout);
1739
1740 if (timeout_valid)
1741 end_time =
1742 g_get_monotonic_time () + timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
1743
1744 g_mutex_lock (&priv->mutex);
1745
1746 while (TRUE) {
1747 GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
1748 if (!priv->started)
1749 goto not_started;
1750
1751 if (priv->preroll_buffer != NULL)
1752 break;
1753
1754 if (priv->is_eos)
1755 goto eos;
1756
1757 /* nothing to return, wait */
1758 GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer");
1759 priv->wait_status |= APP_WAITING;
1760 if (timeout_valid) {
1761 if (!g_cond_wait_until (&priv->cond, &priv->mutex, end_time))
1762 goto expired;
1763 } else {
1764 g_cond_wait (&priv->cond, &priv->mutex);
1765 }
1766 priv->wait_status &= ~APP_WAITING;
1767 }
1768 sample =
1769 gst_sample_new (priv->preroll_buffer, priv->preroll_caps,
1770 &priv->preroll_segment, NULL);
1771 gst_buffer_replace (&priv->preroll_buffer, NULL);
1772 GST_DEBUG_OBJECT (appsink, "we have the preroll sample %p", sample);
1773 g_mutex_unlock (&priv->mutex);
1774
1775 return sample;
1776
1777 /* special conditions */
1778 expired:
1779 {
1780 GST_DEBUG_OBJECT (appsink, "timeout expired, return NULL");
1781 priv->wait_status &= ~APP_WAITING;
1782 g_mutex_unlock (&priv->mutex);
1783 return NULL;
1784 }
1785 eos:
1786 {
1787 GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
1788 g_mutex_unlock (&priv->mutex);
1789 return NULL;
1790 }
1791 not_started:
1792 {
1793 GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
1794 g_mutex_unlock (&priv->mutex);
1795 return NULL;
1796 }
1797 }
1798
1799 /**
1800 * gst_app_sink_try_pull_sample:
1801 * @appsink: a #GstAppSink
1802 * @timeout: the maximum amount of time to wait for a sample
1803 *
1804 * This function blocks until a sample or EOS becomes available or the appsink
1805 * element is set to the READY/NULL state or the timeout expires.
1806 *
1807 * This function will only return samples when the appsink is in the PLAYING
1808 * state. All rendered buffers will be put in a queue so that the application
1809 * can pull samples at its own rate. Note that when the application does not
1810 * pull samples fast enough, the queued buffers could consume a lot of memory,
1811 * especially when dealing with raw video frames.
1812 *
1813 * If an EOS event was received before any buffers or the timeout expires,
1814 * this function returns %NULL. Use gst_app_sink_is_eos () to check for the EOS
1815 * condition.
1816 *
1817 * Returns: (transfer full) (nullable): a #GstSample or NULL when the appsink is stopped or EOS or the timeout expires.
1818 * Call gst_sample_unref() after usage.
1819 *
1820 * Since: 1.10
1821 */
1822 GstSample *
gst_app_sink_try_pull_sample(GstAppSink * appsink,GstClockTime timeout)1823 gst_app_sink_try_pull_sample (GstAppSink * appsink, GstClockTime timeout)
1824 {
1825 while (TRUE) {
1826 GstMiniObject *obj;
1827
1828 obj = gst_app_sink_try_pull_object (appsink, timeout);
1829
1830 if (!obj) {
1831 return NULL;
1832 } else if (GST_IS_SAMPLE (obj)) {
1833 return GST_SAMPLE_CAST (obj);
1834 } else {
1835 gst_mini_object_unref (obj);
1836 }
1837 }
1838 }
1839
1840 /**
1841 * gst_app_sink_try_pull_object: (skip)
1842 * @appsink: a #GstAppSink
1843 * @timeout: the maximum amount of time to wait for a sample
1844 *
1845 * This function blocks until a sample or an event or EOS becomes available or the appsink
1846 * element is set to the READY/NULL state or the timeout expires.
1847 *
1848 * This function will only return samples when the appsink is in the PLAYING
1849 * state. All rendered buffers and events will be put in a queue so that the application
1850 * can pull them at its own rate. Note that when the application does not
1851 * pull samples fast enough, the queued buffers could consume a lot of memory,
1852 * especially when dealing with raw video frames.
1853 * Events can be pulled when the appsink is in the READY, PAUSED or PLAYING state.
1854 *
1855 * This function will only pull serialized events, excluding
1856 * the EOS event for which this functions returns
1857 * %NULL. Use gst_app_sink_is_eos() to check for the EOS condition.
1858 *
1859 * This method is a variant of gst_app_sink_try_pull_sample() that can be used
1860 * to handle incoming events events as well as samples.
1861 *
1862 * Note that future releases may extend this API to return other object types
1863 * so make sure that your code is checking for the actual type it is handling.
1864 *
1865 * Returns: (transfer full): a #GstSample, or #GstEvent or NULL when the appsink is stopped or EOS or the timeout expires.
1866 * Call gst_mini_object_unref() after usage.
1867 *
1868 * Since: 1.20
1869 */
1870 GstMiniObject *
gst_app_sink_try_pull_object(GstAppSink * appsink,GstClockTime timeout)1871 gst_app_sink_try_pull_object (GstAppSink * appsink, GstClockTime timeout)
1872 {
1873 GstAppSinkPrivate *priv;
1874 GstMiniObject *obj = NULL, *ret;
1875 gboolean timeout_valid;
1876 gint64 end_time;
1877
1878 g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
1879
1880 timeout_valid = GST_CLOCK_TIME_IS_VALID (timeout);
1881
1882 if (timeout_valid)
1883 end_time =
1884 g_get_monotonic_time () + timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
1885
1886 priv = appsink->priv;
1887
1888 g_mutex_lock (&priv->mutex);
1889 gst_buffer_replace (&priv->preroll_buffer, NULL);
1890
1891 while (TRUE) {
1892 GST_DEBUG_OBJECT (appsink, "trying to grab an object");
1893 if (!priv->started)
1894 goto not_started;
1895
1896 if (priv->num_buffers > 0 || priv->num_events > 0)
1897 break;
1898
1899 if (priv->is_eos)
1900 goto eos;
1901
1902 /* nothing to return, wait */
1903 GST_DEBUG_OBJECT (appsink, "waiting for an object");
1904 priv->wait_status |= APP_WAITING;
1905 if (timeout_valid) {
1906 if (!g_cond_wait_until (&priv->cond, &priv->mutex, end_time))
1907 goto expired;
1908 } else {
1909 g_cond_wait (&priv->cond, &priv->mutex);
1910 }
1911 priv->wait_status &= ~APP_WAITING;
1912 }
1913
1914 obj = dequeue_object (appsink);
1915
1916 /* convert buffer and buffer list to sample */
1917 if (GST_IS_BUFFER (obj)) {
1918 GST_DEBUG_OBJECT (appsink, "we have a buffer %p", obj);
1919 priv->sample = gst_sample_make_writable (priv->sample);
1920 gst_sample_set_buffer_list (priv->sample, NULL);
1921 gst_sample_set_buffer (priv->sample, GST_BUFFER_CAST (obj));
1922 ret = GST_MINI_OBJECT_CAST (gst_sample_ref (priv->sample));
1923 gst_mini_object_unref (obj);
1924 } else if (GST_IS_BUFFER_LIST (obj)) {
1925 GST_DEBUG_OBJECT (appsink, "we have a list %p", obj);
1926 priv->sample = gst_sample_make_writable (priv->sample);
1927 gst_sample_set_buffer (priv->sample, NULL);
1928 gst_sample_set_buffer_list (priv->sample, GST_BUFFER_LIST_CAST (obj));
1929 ret = GST_MINI_OBJECT_CAST (gst_sample_ref (priv->sample));
1930 gst_mini_object_unref (obj);
1931 } else {
1932 ret = obj;
1933 }
1934
1935 if ((priv->wait_status & STREAM_WAITING))
1936 g_cond_signal (&priv->cond);
1937
1938 g_mutex_unlock (&priv->mutex);
1939
1940 return ret;
1941
1942 /* special conditions */
1943 expired:
1944 {
1945 GST_DEBUG_OBJECT (appsink, "timeout expired, return NULL");
1946 priv->wait_status &= ~APP_WAITING;
1947 g_mutex_unlock (&priv->mutex);
1948 return NULL;
1949 }
1950 eos:
1951 {
1952 GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
1953 g_mutex_unlock (&priv->mutex);
1954 return NULL;
1955 }
1956 not_started:
1957 {
1958 GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
1959 g_mutex_unlock (&priv->mutex);
1960 return NULL;
1961 }
1962 }
1963
1964 /**
1965 * gst_app_sink_set_callbacks: (skip)
1966 * @appsink: a #GstAppSink
1967 * @callbacks: the callbacks
1968 * @user_data: a user_data argument for the callbacks
1969 * @notify: a destroy notify function
1970 *
1971 * Set callbacks which will be executed for each new preroll, new sample and eos.
1972 * This is an alternative to using the signals, it has lower overhead and is thus
1973 * less expensive, but also less flexible.
1974 *
1975 * If callbacks are installed, no signals will be emitted for performance
1976 * reasons.
1977 *
1978 * Before 1.16.3 it was not possible to change the callbacks in a thread-safe
1979 * way.
1980 */
1981 void
gst_app_sink_set_callbacks(GstAppSink * appsink,GstAppSinkCallbacks * callbacks,gpointer user_data,GDestroyNotify notify)1982 gst_app_sink_set_callbacks (GstAppSink * appsink,
1983 GstAppSinkCallbacks * callbacks, gpointer user_data, GDestroyNotify notify)
1984 {
1985 Callbacks *old_callbacks, *new_callbacks = NULL;
1986 GstAppSinkPrivate *priv;
1987
1988 g_return_if_fail (GST_IS_APP_SINK (appsink));
1989 g_return_if_fail (callbacks != NULL);
1990
1991 priv = appsink->priv;
1992
1993 if (callbacks) {
1994 new_callbacks = g_new0 (Callbacks, 1);
1995 new_callbacks->callbacks = *callbacks;
1996 new_callbacks->user_data = user_data;
1997 new_callbacks->destroy_notify = notify;
1998 new_callbacks->ref_count = 1;
1999 }
2000
2001 g_mutex_lock (&priv->mutex);
2002 old_callbacks = g_steal_pointer (&priv->callbacks);
2003 priv->callbacks = g_steal_pointer (&new_callbacks);
2004 g_mutex_unlock (&priv->mutex);
2005
2006 g_clear_pointer (&old_callbacks, callbacks_unref);
2007 }
2008
2009 /*** GSTURIHANDLER INTERFACE *************************************************/
2010
2011 static GstURIType
gst_app_sink_uri_get_type(GType type)2012 gst_app_sink_uri_get_type (GType type)
2013 {
2014 return GST_URI_SINK;
2015 }
2016
2017 static const gchar *const *
gst_app_sink_uri_get_protocols(GType type)2018 gst_app_sink_uri_get_protocols (GType type)
2019 {
2020 static const gchar *protocols[] = { "appsink", NULL };
2021
2022 return protocols;
2023 }
2024
2025 static gchar *
gst_app_sink_uri_get_uri(GstURIHandler * handler)2026 gst_app_sink_uri_get_uri (GstURIHandler * handler)
2027 {
2028 return g_strdup ("appsink");
2029 }
2030
2031 static gboolean
gst_app_sink_uri_set_uri(GstURIHandler * handler,const gchar * uri,GError ** error)2032 gst_app_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri,
2033 GError ** error)
2034 {
2035 /* GstURIHandler checks the protocol for us */
2036 return TRUE;
2037 }
2038
2039 static void
gst_app_sink_uri_handler_init(gpointer g_iface,gpointer iface_data)2040 gst_app_sink_uri_handler_init (gpointer g_iface, gpointer iface_data)
2041 {
2042 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
2043
2044 iface->get_type = gst_app_sink_uri_get_type;
2045 iface->get_protocols = gst_app_sink_uri_get_protocols;
2046 iface->get_uri = gst_app_sink_uri_get_uri;
2047 iface->set_uri = gst_app_sink_uri_set_uri;
2048
2049 }
2050