• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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