tizen 2.3 release
[framework/multimedia/gst-plugins-base0.10.git] / gst-libs / gst / app / gstappsink.c
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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 /**
21  * SECTION:gstappsink
22  * @short_description: Easy way for applications to extract buffers from a
23  *     pipeline
24  * @see_also: #GstBaseSink, appsrc
25  *
26  * Appsink is a sink plugin that supports many different methods for making
27  * the application get a handle on the GStreamer data in a pipeline. Unlike
28  * most GStreamer elements, Appsink provides external API functions.
29  *
30  * appsink can be used by linking to the gstappsink.h header file to access the
31  * methods or by using the appsink action signals and properties.
32  *
33  * The normal way of retrieving buffers from appsink is by using the
34  * gst_app_sink_pull_buffer() and gst_app_sink_pull_preroll() methods.
35  * These methods block until a buffer becomes available in the sink or when the
36  * sink is shut down or reaches EOS.
37  *
38  * Appsink will internally use a queue to collect buffers from the streaming
39  * thread. If the application is not pulling buffers fast enough, this queue
40  * will consume a lot of memory over time. The "max-buffers" property can be
41  * used to limit the queue size. The "drop" property controls whether the
42  * streaming thread blocks or if older buffers are dropped when the maximum
43  * queue size is reached. Note that blocking the streaming thread can negatively
44  * affect real-time performance and should be avoided.
45  *
46  * If a blocking behaviour is not desirable, setting the "emit-signals" property
47  * to %TRUE will make appsink emit the "new-buffer" and "new-preroll" signals
48  * when a buffer can be pulled without blocking.
49  *
50  * The "caps" property on appsink can be used to control the formats that
51  * appsink can receive. This property can contain non-fixed caps, the format of
52  * the pulled buffers can be obtained by getting the buffer caps.
53  *
54  * If one of the pull-preroll or pull-buffer methods return %NULL, the appsink
55  * is stopped or in the EOS state. You can check for the EOS state with the
56  * "eos" property or with the gst_app_sink_is_eos() method.
57  *
58  * The eos signal can also be used to be informed when the EOS state is reached
59  * to avoid polling.
60  *
61  * Last reviewed on 2008-12-17 (0.10.22)
62  *
63  * Since: 0.10.22
64  */
65
66 #ifdef HAVE_CONFIG_H
67 #include "config.h"
68 #endif
69
70 #include <gst/gst.h>
71 #include <gst/base/gstbasesink.h>
72 #include <gst/gstbuffer.h>
73 #include <gst/gstbufferlist.h>
74
75 #include <string.h>
76
77 #include "gstappsink.h"
78
79 #include "gst/glib-compat-private.h"
80
81 struct _GstAppSinkPrivate
82 {
83   GstCaps *caps;
84   gboolean emit_signals;
85   guint max_buffers;
86   gboolean drop;
87
88   GCond *cond;
89   GMutex *mutex;
90   GQueue *queue;
91   GstBuffer *preroll;
92   gboolean flushing;
93   gboolean unlock;
94   gboolean started;
95   gboolean is_eos;
96
97   GstAppSinkCallbacks callbacks;
98   gpointer user_data;
99   GDestroyNotify notify;
100
101   gboolean buffer_lists_supported;
102 };
103
104 GST_DEBUG_CATEGORY_STATIC (app_sink_debug);
105 #define GST_CAT_DEFAULT app_sink_debug
106
107 enum
108 {
109   /* signals */
110   SIGNAL_EOS,
111   SIGNAL_NEW_PREROLL,
112   SIGNAL_NEW_BUFFER,
113   SIGNAL_NEW_BUFFER_LIST,
114
115   /* actions */
116   SIGNAL_PULL_PREROLL,
117   SIGNAL_PULL_BUFFER,
118   SIGNAL_PULL_BUFFER_LIST,
119
120   LAST_SIGNAL
121 };
122
123 #define DEFAULT_PROP_EOS                TRUE
124 #define DEFAULT_PROP_EMIT_SIGNALS       FALSE
125 #define DEFAULT_PROP_MAX_BUFFERS        0
126 #define DEFAULT_PROP_DROP               FALSE
127
128 enum
129 {
130   PROP_0,
131   PROP_CAPS,
132   PROP_EOS,
133   PROP_EMIT_SIGNALS,
134   PROP_MAX_BUFFERS,
135   PROP_DROP,
136   PROP_LAST
137 };
138
139 static GstStaticPadTemplate gst_app_sink_template =
140 GST_STATIC_PAD_TEMPLATE ("sink",
141     GST_PAD_SINK,
142     GST_PAD_ALWAYS,
143     GST_STATIC_CAPS_ANY);
144
145 static void gst_app_sink_uri_handler_init (gpointer g_iface,
146     gpointer iface_data);
147
148 static void gst_app_sink_dispose (GObject * object);
149 static void gst_app_sink_finalize (GObject * object);
150
151 static void gst_app_sink_set_property (GObject * object, guint prop_id,
152     const GValue * value, GParamSpec * pspec);
153 static void gst_app_sink_get_property (GObject * object, guint prop_id,
154     GValue * value, GParamSpec * pspec);
155
156 static gboolean gst_app_sink_unlock_start (GstBaseSink * bsink);
157 static gboolean gst_app_sink_unlock_stop (GstBaseSink * bsink);
158 static gboolean gst_app_sink_start (GstBaseSink * psink);
159 static gboolean gst_app_sink_stop (GstBaseSink * psink);
160 static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
161 static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
162     GstBuffer * buffer);
163 static GstFlowReturn gst_app_sink_render_common (GstBaseSink * psink,
164     GstMiniObject * data, gboolean is_list);
165 static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
166     GstBuffer * buffer);
167 static GstFlowReturn gst_app_sink_render_list (GstBaseSink * psink,
168     GstBufferList * list);
169 static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink);
170 static GstMiniObject *gst_app_sink_pull_object (GstAppSink * appsink);
171
172 static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
173
174 static void
175 _do_init (GType filesrc_type)
176 {
177   static const GInterfaceInfo urihandler_info = {
178     gst_app_sink_uri_handler_init,
179     NULL,
180     NULL
181   };
182   g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER,
183       &urihandler_info);
184 }
185
186 GST_BOILERPLATE_FULL (GstAppSink, gst_app_sink, GstBaseSink, GST_TYPE_BASE_SINK,
187     _do_init);
188
189 /* Can't use glib-genmarshal for this, as it doesn't know how to handle
190  * GstMiniObject-based types, which are a new fundamental type */
191 static void
192 gst_app_marshal_BUFFER__VOID (GClosure * closure,
193     GValue * return_value,
194     guint n_param_values,
195     const GValue * param_values,
196     gpointer invocation_hint, gpointer marshal_data)
197 {
198   typedef GstBuffer *(*GMarshalFunc_BUFFER__VOID) (gpointer data1,
199       gpointer data2);
200   register GMarshalFunc_BUFFER__VOID callback;
201   register GCClosure *cc = (GCClosure *) closure;
202   register gpointer data1, data2;
203   GstBuffer *v_return;
204
205   g_return_if_fail (return_value != NULL);
206   g_return_if_fail (n_param_values == 1);
207
208   if (G_CCLOSURE_SWAP_DATA (closure)) {
209     data1 = closure->data;
210     data2 = g_value_peek_pointer (param_values + 0);
211   } else {
212     data1 = g_value_peek_pointer (param_values + 0);
213     data2 = closure->data;
214   }
215   callback =
216       (GMarshalFunc_BUFFER__VOID) (marshal_data ? marshal_data : cc->callback);
217
218   v_return = callback (data1, data2);
219
220   gst_value_take_buffer (return_value, v_return);
221 }
222
223 static void
224 gst_app_sink_base_init (gpointer g_class)
225 {
226   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
227
228   GST_DEBUG_CATEGORY_INIT (app_sink_debug, "appsink", 0, "appsink element");
229
230   gst_element_class_set_details_simple (element_class, "AppSink",
231       "Generic/Sink", "Allow the application to get access to raw buffer",
232       "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com>");
233
234   gst_element_class_add_static_pad_template (element_class,
235       &gst_app_sink_template);
236 }
237
238 static void
239 gst_app_sink_class_init (GstAppSinkClass * klass)
240 {
241   GObjectClass *gobject_class = (GObjectClass *) klass;
242   GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
243
244   gobject_class->dispose = gst_app_sink_dispose;
245   gobject_class->finalize = gst_app_sink_finalize;
246
247   gobject_class->set_property = gst_app_sink_set_property;
248   gobject_class->get_property = gst_app_sink_get_property;
249
250   g_object_class_install_property (gobject_class, PROP_CAPS,
251       g_param_spec_boxed ("caps", "Caps",
252           "The allowed caps for the sink pad", GST_TYPE_CAPS,
253           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
254
255   g_object_class_install_property (gobject_class, PROP_EOS,
256       g_param_spec_boolean ("eos", "EOS",
257           "Check if the sink is EOS or not started", DEFAULT_PROP_EOS,
258           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
259
260   g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
261       g_param_spec_boolean ("emit-signals", "Emit signals",
262           "Emit new-preroll, new-buffer and new-buffer-list signals",
263           DEFAULT_PROP_EMIT_SIGNALS,
264           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
265
266   g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
267       g_param_spec_uint ("max-buffers", "Max Buffers",
268           "The maximum number of buffers to queue internally (0 = unlimited)",
269           0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
270           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
271
272   g_object_class_install_property (gobject_class, PROP_DROP,
273       g_param_spec_boolean ("drop", "Drop",
274           "Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
275           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
276
277   /**
278    * GstAppSink::eos:
279    * @appsink: the appsink element that emitted the signal
280    *
281    * Signal that the end-of-stream has been reached. This signal is emitted from
282    * the steaming thread.
283    */
284   gst_app_sink_signals[SIGNAL_EOS] =
285       g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
286       G_STRUCT_OFFSET (GstAppSinkClass, eos),
287       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
288   /**
289    * GstAppSink::new-preroll:
290    * @appsink: the appsink element that emitted the signal
291    *
292    * Signal that a new preroll buffer is available.
293    *
294    * This signal is emitted from the steaming thread and only when the
295    * "emit-signals" property is %TRUE.
296    *
297    * The new preroll buffer can be retrieved with the "pull-preroll" action
298    * signal or gst_app_sink_pull_preroll() either from this signal callback
299    * or from any other thread.
300    *
301    * Note that this signal is only emitted when the "emit-signals" property is
302    * set to %TRUE, which it is not by default for performance reasons.
303    */
304   gst_app_sink_signals[SIGNAL_NEW_PREROLL] =
305       g_signal_new ("new-preroll", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
306       G_STRUCT_OFFSET (GstAppSinkClass, new_preroll),
307       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
308   /**
309    * GstAppSink::new-buffer:
310    * @appsink: the appsink element that emitted the signal
311    *
312    * Signal that a new buffer is available.
313    *
314    * This signal is emitted from the steaming thread and only when the
315    * "emit-signals" property is %TRUE.
316    *
317    * The new buffer can be retrieved with the "pull-buffer" action
318    * signal or gst_app_sink_pull_buffer() either from this signal callback
319    * or from any other thread.
320    *
321    * Note that this signal is only emitted when the "emit-signals" property is
322    * set to %TRUE, which it is not by default for performance reasons.
323    */
324   gst_app_sink_signals[SIGNAL_NEW_BUFFER] =
325       g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
326       G_STRUCT_OFFSET (GstAppSinkClass, new_buffer),
327       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
328   /**
329    * GstAppSink::new-buffer-list:
330    * @appsink: the appsink element that emitted the signal
331    *
332    * Signal that a new bufferlist is available.
333    *
334    * This signal is emitted from the steaming thread and only when the
335    * "emit-signals" property is %TRUE.
336    *
337    * The new buffer can be retrieved with the "pull-buffer-list" action
338    * signal or gst_app_sink_pull_buffer_list() either from this signal callback
339    * or from any other thread.
340    *
341    * Note that this signal is only emitted when the "emit-signals" property is
342    * set to %TRUE, which it is not by default for performance reasons.
343    */
344   gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST] =
345       g_signal_new ("new-buffer-list", G_TYPE_FROM_CLASS (klass),
346       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, new_buffer_list),
347       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
348
349   /**
350    * GstAppSink::pull-preroll:
351    * @appsink: the appsink element to emit this signal on
352    *
353    * Get the last preroll buffer in @appsink. This was the buffer that caused the
354    * appsink to preroll in the PAUSED state. This buffer can be pulled many times
355    * and remains available to the application even after EOS.
356    *
357    * This function is typically used when dealing with a pipeline in the PAUSED
358    * state. Calling this function after doing a seek will give the buffer right
359    * after the seek position.
360    *
361    * Note that the preroll buffer will also be returned as the first buffer
362    * when calling gst_app_sink_pull_buffer() or the "pull-buffer" action signal.
363    *
364    * If an EOS event was received before any buffers, this function returns
365    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
366    *
367    * This function blocks until a preroll buffer or EOS is received or the appsink
368    * element is set to the READY/NULL state.
369    *
370    * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
371    */
372   gst_app_sink_signals[SIGNAL_PULL_PREROLL] =
373       g_signal_new ("pull-preroll", G_TYPE_FROM_CLASS (klass),
374       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
375           pull_preroll), NULL, NULL, gst_app_marshal_BUFFER__VOID,
376       GST_TYPE_BUFFER, 0, G_TYPE_NONE);
377   /**
378    * GstAppSink::pull-buffer:
379    * @appsink: the appsink element to emit this signal on
380    *
381    * This function blocks until a buffer or EOS becomes available or the appsink
382    * element is set to the READY/NULL state.
383    *
384    * This function will only return buffers when the appsink is in the PLAYING
385    * state. All rendered buffers will be put in a queue so that the application
386    * can pull buffers at its own rate.
387    *
388    * Note that when the application does not pull buffers fast enough, the
389    * queued buffers could consume a lot of memory, especially when dealing with
390    * raw video frames. It's possible to control the behaviour of the queue with
391    * the "drop" and "max-buffers" properties.
392    *
393    * If an EOS event was received before any buffers, this function returns
394    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
395    *
396    * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
397    */
398   gst_app_sink_signals[SIGNAL_PULL_BUFFER] =
399       g_signal_new ("pull-buffer", G_TYPE_FROM_CLASS (klass),
400       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
401           pull_buffer), NULL, NULL, gst_app_marshal_BUFFER__VOID,
402       GST_TYPE_BUFFER, 0, G_TYPE_NONE);
403   /**
404    * GstAppSink::pull-buffer-list:
405    * @appsink: the appsink element to emit this signal on
406    *
407    * This function blocks until a buffer list or EOS becomes available or the appsink
408    * element is set to the READY/NULL state.
409    *
410    * This function will only return bufferlists when the appsink is in the PLAYING
411    * state. All rendered bufferlists will be put in a queue so that the application
412    * can pull bufferlists at its own rate.
413    *
414    * Note that when the application does not pull bufferlists fast enough, the
415    * queued bufferlists could consume a lot of memory, especially when dealing with
416    * raw video frames. It's possible to control the behaviour of the queue with
417    * the "drop" and "max-buffers" properties.
418    *
419    * If an EOS event was received before any buffers, this function returns
420    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
421    *
422    * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
423    */
424   gst_app_sink_signals[SIGNAL_PULL_BUFFER_LIST] =
425       g_signal_new ("pull-buffer-list", G_TYPE_FROM_CLASS (klass),
426       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
427           pull_buffer_list), NULL, NULL, gst_app_marshal_BUFFER__VOID,
428       GST_TYPE_BUFFER_LIST, 0, G_TYPE_NONE);
429
430   basesink_class->unlock = gst_app_sink_unlock_start;
431   basesink_class->unlock_stop = gst_app_sink_unlock_stop;
432   basesink_class->start = gst_app_sink_start;
433   basesink_class->stop = gst_app_sink_stop;
434   basesink_class->event = gst_app_sink_event;
435   basesink_class->preroll = gst_app_sink_preroll;
436   basesink_class->render = gst_app_sink_render;
437   basesink_class->render_list = gst_app_sink_render_list;
438   basesink_class->get_caps = gst_app_sink_getcaps;
439
440   klass->pull_preroll = gst_app_sink_pull_preroll;
441   klass->pull_buffer = gst_app_sink_pull_buffer;
442   klass->pull_buffer_list = gst_app_sink_pull_buffer_list;
443
444   g_type_class_add_private (klass, sizeof (GstAppSinkPrivate));
445 }
446
447 static void
448 gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass)
449 {
450   GstAppSinkPrivate *priv;
451
452   priv = appsink->priv =
453       G_TYPE_INSTANCE_GET_PRIVATE (appsink, GST_TYPE_APP_SINK,
454       GstAppSinkPrivate);
455
456   priv->mutex = g_mutex_new ();
457   priv->cond = g_cond_new ();
458   priv->queue = g_queue_new ();
459
460   priv->emit_signals = DEFAULT_PROP_EMIT_SIGNALS;
461   priv->max_buffers = DEFAULT_PROP_MAX_BUFFERS;
462   priv->drop = DEFAULT_PROP_DROP;
463 }
464
465 static void
466 gst_app_sink_dispose (GObject * obj)
467 {
468   GstAppSink *appsink = GST_APP_SINK_CAST (obj);
469   GstAppSinkPrivate *priv = appsink->priv;
470   GstMiniObject *queue_obj;
471
472   GST_OBJECT_LOCK (appsink);
473   if (priv->caps) {
474     gst_caps_unref (priv->caps);
475     priv->caps = NULL;
476   }
477   if (priv->notify) {
478     priv->notify (priv->user_data);
479   }
480   priv->user_data = NULL;
481   priv->notify = NULL;
482
483   GST_OBJECT_UNLOCK (appsink);
484
485   g_mutex_lock (priv->mutex);
486   if (priv->preroll) {
487     gst_buffer_unref (priv->preroll);
488     priv->preroll = NULL;
489   }
490   while ((queue_obj = g_queue_pop_head (priv->queue)))
491     gst_mini_object_unref (queue_obj);
492   g_mutex_unlock (priv->mutex);
493
494   G_OBJECT_CLASS (parent_class)->dispose (obj);
495 }
496
497 static void
498 gst_app_sink_finalize (GObject * obj)
499 {
500   GstAppSink *appsink = GST_APP_SINK_CAST (obj);
501   GstAppSinkPrivate *priv = appsink->priv;
502
503   g_mutex_free (priv->mutex);
504   g_cond_free (priv->cond);
505   g_queue_free (priv->queue);
506
507   G_OBJECT_CLASS (parent_class)->finalize (obj);
508 }
509
510 static void
511 gst_app_sink_set_property (GObject * object, guint prop_id,
512     const GValue * value, GParamSpec * pspec)
513 {
514   GstAppSink *appsink = GST_APP_SINK_CAST (object);
515
516   switch (prop_id) {
517     case PROP_CAPS:
518       gst_app_sink_set_caps (appsink, gst_value_get_caps (value));
519       break;
520     case PROP_EMIT_SIGNALS:
521       gst_app_sink_set_emit_signals (appsink, g_value_get_boolean (value));
522       break;
523     case PROP_MAX_BUFFERS:
524       gst_app_sink_set_max_buffers (appsink, g_value_get_uint (value));
525       break;
526     case PROP_DROP:
527       gst_app_sink_set_drop (appsink, g_value_get_boolean (value));
528       break;
529     default:
530       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
531       break;
532   }
533 }
534
535 static void
536 gst_app_sink_get_property (GObject * object, guint prop_id, GValue * value,
537     GParamSpec * pspec)
538 {
539   GstAppSink *appsink = GST_APP_SINK_CAST (object);
540
541   switch (prop_id) {
542     case PROP_CAPS:
543     {
544       GstCaps *caps;
545
546       caps = gst_app_sink_get_caps (appsink);
547       gst_value_set_caps (value, caps);
548       if (caps)
549         gst_caps_unref (caps);
550       break;
551     }
552     case PROP_EOS:
553       g_value_set_boolean (value, gst_app_sink_is_eos (appsink));
554       break;
555     case PROP_EMIT_SIGNALS:
556       g_value_set_boolean (value, gst_app_sink_get_emit_signals (appsink));
557       break;
558     case PROP_MAX_BUFFERS:
559       g_value_set_uint (value, gst_app_sink_get_max_buffers (appsink));
560       break;
561     case PROP_DROP:
562       g_value_set_boolean (value, gst_app_sink_get_drop (appsink));
563       break;
564     default:
565       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
566       break;
567   }
568 }
569
570 static gboolean
571 gst_app_sink_unlock_start (GstBaseSink * bsink)
572 {
573   GstAppSink *appsink = GST_APP_SINK_CAST (bsink);
574   GstAppSinkPrivate *priv = appsink->priv;
575
576   g_mutex_lock (priv->mutex);
577   GST_DEBUG_OBJECT (appsink, "unlock start");
578   priv->unlock = TRUE;
579   g_cond_signal (priv->cond);
580   g_mutex_unlock (priv->mutex);
581
582   return TRUE;
583 }
584
585 static gboolean
586 gst_app_sink_unlock_stop (GstBaseSink * bsink)
587 {
588   GstAppSink *appsink = GST_APP_SINK_CAST (bsink);
589   GstAppSinkPrivate *priv = appsink->priv;
590
591   g_mutex_lock (priv->mutex);
592   GST_DEBUG_OBJECT (appsink, "unlock stop");
593   priv->unlock = FALSE;
594   g_cond_signal (priv->cond);
595   g_mutex_unlock (priv->mutex);
596
597   return TRUE;
598 }
599
600 static void
601 gst_app_sink_flush_unlocked (GstAppSink * appsink)
602 {
603   GstMiniObject *obj;
604   GstAppSinkPrivate *priv = appsink->priv;
605
606   GST_DEBUG_OBJECT (appsink, "flush stop appsink");
607   priv->is_eos = FALSE;
608   gst_buffer_replace (&priv->preroll, NULL);
609   while ((obj = g_queue_pop_head (priv->queue)))
610     gst_mini_object_unref (obj);
611   g_cond_signal (priv->cond);
612 }
613
614 #define NEW_BUFFER_LIST_SIGID \
615     gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST]
616
617 static gboolean
618 gst_app_sink_check_buffer_lists_support (GstAppSink * appsink)
619 {
620   gboolean ret;
621
622   ret = (appsink->priv->callbacks.new_buffer_list != NULL) ||
623       g_signal_has_handler_pending (appsink, NEW_BUFFER_LIST_SIGID, 0, FALSE);
624
625   GST_INFO_OBJECT (appsink, "application supports buffer lists: %d", ret);
626   return ret;
627 }
628
629 static gboolean
630 gst_app_sink_start (GstBaseSink * psink)
631 {
632   GstAppSink *appsink = GST_APP_SINK_CAST (psink);
633   GstAppSinkPrivate *priv = appsink->priv;
634
635   g_mutex_lock (priv->mutex);
636   GST_DEBUG_OBJECT (appsink, "starting");
637   priv->flushing = FALSE;
638   priv->started = TRUE;
639   priv->buffer_lists_supported =
640       gst_app_sink_check_buffer_lists_support (appsink);
641   g_mutex_unlock (priv->mutex);
642
643   return TRUE;
644 }
645
646 static gboolean
647 gst_app_sink_stop (GstBaseSink * psink)
648 {
649   GstAppSink *appsink = GST_APP_SINK_CAST (psink);
650   GstAppSinkPrivate *priv = appsink->priv;
651
652   g_mutex_lock (priv->mutex);
653   GST_DEBUG_OBJECT (appsink, "stopping");
654   priv->flushing = TRUE;
655   priv->started = FALSE;
656   gst_app_sink_flush_unlocked (appsink);
657   g_mutex_unlock (priv->mutex);
658
659   return TRUE;
660 }
661
662 static gboolean
663 gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
664 {
665   GstAppSink *appsink = GST_APP_SINK_CAST (sink);
666   GstAppSinkPrivate *priv = appsink->priv;
667
668   switch (event->type) {
669     case GST_EVENT_EOS:
670
671       g_mutex_lock (priv->mutex);
672       GST_DEBUG_OBJECT (appsink, "receiving EOS");
673       priv->is_eos = TRUE;
674       g_cond_signal (priv->cond);
675       g_mutex_unlock (priv->mutex);
676
677       /* emit EOS now */
678       if (priv->callbacks.eos)
679         priv->callbacks.eos (appsink, priv->user_data);
680       else
681         g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_EOS], 0);
682
683       break;
684     case GST_EVENT_FLUSH_START:
685       /* we don't have to do anything here, the base class will call unlock
686        * which will make sure we exit the _render method */
687       GST_DEBUG_OBJECT (appsink, "received FLUSH_START");
688       break;
689     case GST_EVENT_FLUSH_STOP:
690       g_mutex_lock (priv->mutex);
691       GST_DEBUG_OBJECT (appsink, "received FLUSH_STOP");
692       gst_app_sink_flush_unlocked (appsink);
693       g_mutex_unlock (priv->mutex);
694       break;
695     default:
696       break;
697   }
698   return TRUE;
699 }
700
701 static GstFlowReturn
702 gst_app_sink_preroll (GstBaseSink * psink, GstBuffer * buffer)
703 {
704   GstFlowReturn res = GST_FLOW_OK;
705   GstAppSink *appsink = GST_APP_SINK_CAST (psink);
706   GstAppSinkPrivate *priv = appsink->priv;
707   gboolean emit;
708
709   g_mutex_lock (priv->mutex);
710   if (priv->flushing)
711     goto flushing;
712
713   GST_DEBUG_OBJECT (appsink, "setting preroll buffer %p", buffer);
714   gst_buffer_replace (&priv->preroll, buffer);
715
716   g_cond_signal (priv->cond);
717   emit = priv->emit_signals;
718   g_mutex_unlock (priv->mutex);
719
720   if (priv->callbacks.new_preroll)
721     res = priv->callbacks.new_preroll (appsink, priv->user_data);
722   else if (emit)
723     g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_PREROLL], 0);
724
725   return res;
726
727 flushing:
728   {
729     GST_DEBUG_OBJECT (appsink, "we are flushing");
730     g_mutex_unlock (priv->mutex);
731     return GST_FLOW_WRONG_STATE;
732   }
733 }
734
735 static GstFlowReturn
736 gst_app_sink_render_common (GstBaseSink * psink, GstMiniObject * data,
737     gboolean is_list)
738 {
739   GstFlowReturn ret;
740   GstAppSink *appsink = GST_APP_SINK_CAST (psink);
741   GstAppSinkPrivate *priv = appsink->priv;
742   gboolean emit;
743
744 restart:
745   g_mutex_lock (priv->mutex);
746   if (priv->flushing)
747     goto flushing;
748
749   GST_DEBUG_OBJECT (appsink, "pushing render buffer%s %p on queue (%d)",
750       is_list ? " list" : "", data, priv->queue->length);
751
752   while (priv->max_buffers > 0 && priv->queue->length >= priv->max_buffers) {
753     if (priv->drop) {
754       GstMiniObject *obj;
755
756       /* we need to drop the oldest buffer/list and try again */
757       obj = g_queue_pop_head (priv->queue);
758       GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", obj);
759       gst_mini_object_unref (obj);
760     } else {
761       GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
762           priv->queue->length, priv->max_buffers);
763
764       if (priv->unlock) {
765         /* we are asked to unlock, call the wait_preroll method */
766         g_mutex_unlock (priv->mutex);
767         if ((ret = gst_base_sink_wait_preroll (psink)) != GST_FLOW_OK)
768           goto stopping;
769
770         /* we are allowed to continue now */
771         goto restart;
772       }
773
774       /* wait for a buffer to be removed or flush */
775       g_cond_wait (priv->cond, priv->mutex);
776       if (priv->flushing)
777         goto flushing;
778     }
779   }
780   /* we need to ref the buffer when pushing it in the queue */
781   g_queue_push_tail (priv->queue, gst_mini_object_ref (data));
782   g_cond_signal (priv->cond);
783   emit = priv->emit_signals;
784   g_mutex_unlock (priv->mutex);
785
786   if (is_list) {
787     if (priv->callbacks.new_buffer_list)
788       priv->callbacks.new_buffer_list (appsink, priv->user_data);
789     else if (emit)
790       g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST], 0);
791   } else {
792     if (priv->callbacks.new_buffer)
793       priv->callbacks.new_buffer (appsink, priv->user_data);
794     else if (emit)
795       g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
796   }
797   return GST_FLOW_OK;
798
799 flushing:
800   {
801     GST_DEBUG_OBJECT (appsink, "we are flushing");
802     g_mutex_unlock (priv->mutex);
803     return GST_FLOW_WRONG_STATE;
804   }
805 stopping:
806   {
807     GST_DEBUG_OBJECT (appsink, "we are stopping");
808     return ret;
809   }
810 }
811
812 static GstFlowReturn
813 gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
814 {
815   return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (buffer),
816       FALSE);
817 }
818
819 static GstFlowReturn
820 gst_app_sink_render_list (GstBaseSink * sink, GstBufferList * list)
821 {
822   GstBufferListIterator *it;
823   GstFlowReturn flow;
824   GstAppSink *appsink;
825   GstBuffer *group;
826
827   appsink = GST_APP_SINK_CAST (sink);
828
829   if (appsink->priv->buffer_lists_supported)
830     return gst_app_sink_render_common (sink, GST_MINI_OBJECT_CAST (list), TRUE);
831
832   /* The application doesn't support buffer lists, extract individual buffers
833    * then and push them one-by-one */
834   GST_INFO_OBJECT (sink, "chaining each group in list as a merged buffer");
835
836   it = gst_buffer_list_iterate (list);
837
838   if (gst_buffer_list_iterator_next_group (it)) {
839     do {
840       group = gst_buffer_list_iterator_merge_group (it);
841       if (group == NULL) {
842         group = gst_buffer_new ();
843         GST_DEBUG_OBJECT (sink, "chaining empty group");
844       } else {
845         GST_DEBUG_OBJECT (sink, "chaining group");
846       }
847       flow = gst_app_sink_render (sink, group);
848       gst_buffer_unref (group);
849     } while (flow == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
850   } else {
851     GST_DEBUG_OBJECT (sink, "chaining empty group");
852     group = gst_buffer_new ();
853     flow = gst_app_sink_render (sink, group);
854     gst_buffer_unref (group);
855   }
856
857   gst_buffer_list_iterator_free (it);
858
859   return flow;
860 }
861
862 static GstCaps *
863 gst_app_sink_getcaps (GstBaseSink * psink)
864 {
865   GstCaps *caps;
866   GstAppSink *appsink = GST_APP_SINK_CAST (psink);
867   GstAppSinkPrivate *priv = appsink->priv;
868
869   GST_OBJECT_LOCK (appsink);
870   if ((caps = priv->caps))
871     gst_caps_ref (caps);
872   GST_DEBUG_OBJECT (appsink, "got caps %" GST_PTR_FORMAT, caps);
873   GST_OBJECT_UNLOCK (appsink);
874
875   return caps;
876 }
877
878 static GstMiniObject *
879 gst_app_sink_pull_object (GstAppSink * appsink)
880 {
881   GstMiniObject *obj = NULL;
882   GstAppSinkPrivate *priv;
883
884   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
885
886   priv = appsink->priv;
887
888   g_mutex_lock (priv->mutex);
889
890   while (TRUE) {
891     GST_DEBUG_OBJECT (appsink, "trying to grab a buffer/list");
892     if (!priv->started)
893       goto not_started;
894
895     if (!g_queue_is_empty (priv->queue))
896       break;
897
898     if (priv->is_eos)
899       goto eos;
900
901     /* nothing to return, wait */
902     GST_DEBUG_OBJECT (appsink, "waiting for a buffer/list");
903     g_cond_wait (priv->cond, priv->mutex);
904   }
905   obj = g_queue_pop_head (priv->queue);
906   GST_DEBUG_OBJECT (appsink, "we have a buffer/list %p", obj);
907   g_cond_signal (priv->cond);
908   g_mutex_unlock (priv->mutex);
909
910   return obj;
911
912   /* special conditions */
913 eos:
914   {
915     GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
916     g_mutex_unlock (priv->mutex);
917     return NULL;
918   }
919 not_started:
920   {
921     GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
922     g_mutex_unlock (priv->mutex);
923     return NULL;
924   }
925 }
926
927 /* external API */
928
929 /**
930  * gst_app_sink_set_caps:
931  * @appsink: a #GstAppSink
932  * @caps: caps to set
933  *
934  * Set the capabilities on the appsink element.  This function takes
935  * a copy of the caps structure. After calling this method, the sink will only
936  * accept caps that match @caps. If @caps is non-fixed, you must check the caps
937  * on the buffers to get the actual used caps.
938  *
939  * Since: 0.10.22
940  */
941 void
942 gst_app_sink_set_caps (GstAppSink * appsink, const GstCaps * caps)
943 {
944   GstCaps *old;
945   GstAppSinkPrivate *priv;
946
947   g_return_if_fail (GST_IS_APP_SINK (appsink));
948
949   priv = appsink->priv;
950
951   GST_OBJECT_LOCK (appsink);
952   GST_DEBUG_OBJECT (appsink, "setting caps to %" GST_PTR_FORMAT, caps);
953   if ((old = priv->caps) != caps) {
954     if (caps)
955       priv->caps = gst_caps_copy (caps);
956     else
957       priv->caps = NULL;
958     if (old)
959       gst_caps_unref (old);
960   }
961   GST_OBJECT_UNLOCK (appsink);
962 }
963
964 /**
965  * gst_app_sink_get_caps:
966  * @appsink: a #GstAppSink
967  *
968  * Get the configured caps on @appsink.
969  *
970  * Returns: the #GstCaps accepted by the sink. gst_caps_unref() after usage.
971  *
972  * Since: 0.10.22
973  */
974 GstCaps *
975 gst_app_sink_get_caps (GstAppSink * appsink)
976 {
977   GstCaps *caps;
978   GstAppSinkPrivate *priv;
979
980   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
981
982   priv = appsink->priv;
983
984   GST_OBJECT_LOCK (appsink);
985   if ((caps = priv->caps))
986     gst_caps_ref (caps);
987   GST_DEBUG_OBJECT (appsink, "getting caps of %" GST_PTR_FORMAT, caps);
988   GST_OBJECT_UNLOCK (appsink);
989
990   return caps;
991 }
992
993 /**
994  * gst_app_sink_is_eos:
995  * @appsink: a #GstAppSink
996  *
997  * Check if @appsink is EOS, which is when no more buffers can be pulled because
998  * an EOS event was received.
999  *
1000  * This function also returns %TRUE when the appsink is not in the PAUSED or
1001  * PLAYING state.
1002  *
1003  * Returns: %TRUE if no more buffers can be pulled and the appsink is EOS.
1004  *
1005  * Since: 0.10.22
1006  */
1007 gboolean
1008 gst_app_sink_is_eos (GstAppSink * appsink)
1009 {
1010   gboolean ret;
1011   GstAppSinkPrivate *priv;
1012
1013   g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1014
1015   priv = appsink->priv;
1016
1017   g_mutex_lock (priv->mutex);
1018   if (!priv->started)
1019     goto not_started;
1020
1021   if (priv->is_eos && g_queue_is_empty (priv->queue)) {
1022     GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty");
1023     ret = TRUE;
1024   } else {
1025     GST_DEBUG_OBJECT (appsink, "we are not yet EOS");
1026     ret = FALSE;
1027   }
1028   g_mutex_unlock (priv->mutex);
1029
1030   return ret;
1031
1032 not_started:
1033   {
1034     GST_DEBUG_OBJECT (appsink, "we are stopped, return TRUE");
1035     g_mutex_unlock (priv->mutex);
1036     return TRUE;
1037   }
1038 }
1039
1040 /**
1041  * gst_app_sink_set_emit_signals:
1042  * @appsink: a #GstAppSink
1043  * @emit: the new state
1044  *
1045  * Make appsink emit the "new-preroll" and "new-buffer" signals. This option is
1046  * by default disabled because signal emission is expensive and unneeded when
1047  * the application prefers to operate in pull mode.
1048  *
1049  * Since: 0.10.22
1050  */
1051 void
1052 gst_app_sink_set_emit_signals (GstAppSink * appsink, gboolean emit)
1053 {
1054   GstAppSinkPrivate *priv;
1055
1056   g_return_if_fail (GST_IS_APP_SINK (appsink));
1057
1058   priv = appsink->priv;
1059
1060   g_mutex_lock (priv->mutex);
1061   priv->emit_signals = emit;
1062   g_mutex_unlock (priv->mutex);
1063 }
1064
1065 /**
1066  * gst_app_sink_get_emit_signals:
1067  * @appsink: a #GstAppSink
1068  *
1069  * Check if appsink will emit the "new-preroll" and "new-buffer" signals.
1070  *
1071  * Returns: %TRUE if @appsink is emitting the "new-preroll" and "new-buffer"
1072  * signals.
1073  *
1074  * Since: 0.10.22
1075  */
1076 gboolean
1077 gst_app_sink_get_emit_signals (GstAppSink * appsink)
1078 {
1079   gboolean result;
1080   GstAppSinkPrivate *priv;
1081
1082   g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1083
1084   priv = appsink->priv;
1085
1086   g_mutex_lock (priv->mutex);
1087   result = priv->emit_signals;
1088   g_mutex_unlock (priv->mutex);
1089
1090   return result;
1091 }
1092
1093 /**
1094  * gst_app_sink_set_max_buffers:
1095  * @appsink: a #GstAppSink
1096  * @max: the maximum number of buffers to queue
1097  *
1098  * Set the maximum amount of buffers that can be queued in @appsink. After this
1099  * amount of buffers are queued in appsink, any more buffers will block upstream
1100  * elements until a buffer is pulled from @appsink.
1101  *
1102  * Since: 0.10.22
1103  */
1104 void
1105 gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max)
1106 {
1107   GstAppSinkPrivate *priv;
1108
1109   g_return_if_fail (GST_IS_APP_SINK (appsink));
1110
1111   priv = appsink->priv;
1112
1113   g_mutex_lock (priv->mutex);
1114   if (max != priv->max_buffers) {
1115     priv->max_buffers = max;
1116     /* signal the change */
1117     g_cond_signal (priv->cond);
1118   }
1119   g_mutex_unlock (priv->mutex);
1120 }
1121
1122 /**
1123  * gst_app_sink_get_max_buffers:
1124  * @appsink: a #GstAppSink
1125  *
1126  * Get the maximum amount of buffers that can be queued in @appsink.
1127  *
1128  * Returns: The maximum amount of buffers that can be queued.
1129  *
1130  * Since: 0.10.22
1131  */
1132 guint
1133 gst_app_sink_get_max_buffers (GstAppSink * appsink)
1134 {
1135   guint result;
1136   GstAppSinkPrivate *priv;
1137
1138   g_return_val_if_fail (GST_IS_APP_SINK (appsink), 0);
1139
1140   priv = appsink->priv;
1141
1142   g_mutex_lock (priv->mutex);
1143   result = priv->max_buffers;
1144   g_mutex_unlock (priv->mutex);
1145
1146   return result;
1147 }
1148
1149 /**
1150  * gst_app_sink_set_drop:
1151  * @appsink: a #GstAppSink
1152  * @drop: the new state
1153  *
1154  * Instruct @appsink to drop old buffers when the maximum amount of queued
1155  * buffers is reached.
1156  *
1157  * Since: 0.10.22
1158  */
1159 void
1160 gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop)
1161 {
1162   GstAppSinkPrivate *priv;
1163
1164   g_return_if_fail (GST_IS_APP_SINK (appsink));
1165
1166   priv = appsink->priv;
1167
1168   g_mutex_lock (priv->mutex);
1169   if (priv->drop != drop) {
1170     priv->drop = drop;
1171     /* signal the change */
1172     g_cond_signal (priv->cond);
1173   }
1174   g_mutex_unlock (priv->mutex);
1175 }
1176
1177 /**
1178  * gst_app_sink_get_drop:
1179  * @appsink: a #GstAppSink
1180  *
1181  * Check if @appsink will drop old buffers when the maximum amount of queued
1182  * buffers is reached.
1183  *
1184  * Returns: %TRUE if @appsink is dropping old buffers when the queue is
1185  * filled.
1186  *
1187  * Since: 0.10.22
1188  */
1189 gboolean
1190 gst_app_sink_get_drop (GstAppSink * appsink)
1191 {
1192   gboolean result;
1193   GstAppSinkPrivate *priv;
1194
1195   g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
1196
1197   priv = appsink->priv;
1198
1199   g_mutex_lock (priv->mutex);
1200   result = priv->drop;
1201   g_mutex_unlock (priv->mutex);
1202
1203   return result;
1204 }
1205
1206 /**
1207  * gst_app_sink_pull_preroll:
1208  * @appsink: a #GstAppSink
1209  *
1210  * Get the last preroll buffer in @appsink. This was the buffer that caused the
1211  * appsink to preroll in the PAUSED state. This buffer can be pulled many times
1212  * and remains available to the application even after EOS.
1213  *
1214  * This function is typically used when dealing with a pipeline in the PAUSED
1215  * state. Calling this function after doing a seek will give the buffer right
1216  * after the seek position.
1217  *
1218  * Note that the preroll buffer will also be returned as the first buffer
1219  * when calling gst_app_sink_pull_buffer().
1220  *
1221  * If an EOS event was received before any buffers, this function returns
1222  * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
1223  *
1224  * This function blocks until a preroll buffer or EOS is received or the appsink
1225  * element is set to the READY/NULL state.
1226  *
1227  * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
1228  *
1229  * Since: 0.10.22
1230  */
1231 GstBuffer *
1232 gst_app_sink_pull_preroll (GstAppSink * appsink)
1233 {
1234   GstBuffer *buf = NULL;
1235   GstAppSinkPrivate *priv;
1236
1237   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
1238
1239   priv = appsink->priv;
1240
1241   g_mutex_lock (priv->mutex);
1242
1243   while (TRUE) {
1244     GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
1245     if (!priv->started)
1246       goto not_started;
1247
1248     if (priv->preroll != NULL)
1249       break;
1250
1251     if (priv->is_eos)
1252       goto eos;
1253
1254     /* nothing to return, wait */
1255     GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer");
1256     g_cond_wait (priv->cond, priv->mutex);
1257   }
1258   buf = gst_buffer_ref (priv->preroll);
1259   GST_DEBUG_OBJECT (appsink, "we have the preroll buffer %p", buf);
1260   g_mutex_unlock (priv->mutex);
1261
1262   return buf;
1263
1264   /* special conditions */
1265 eos:
1266   {
1267     GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
1268     g_mutex_unlock (priv->mutex);
1269     return NULL;
1270   }
1271 not_started:
1272   {
1273     GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
1274     g_mutex_unlock (priv->mutex);
1275     return NULL;
1276   }
1277 }
1278
1279 /**
1280  * gst_app_sink_pull_buffer:
1281  * @appsink: a #GstAppSink
1282  *
1283  * This function blocks until a buffer or EOS becomes available or the appsink
1284  * element is set to the READY/NULL state.
1285  *
1286  * This function will only return buffers when the appsink is in the PLAYING
1287  * state. All rendered buffers will be put in a queue so that the application
1288  * can pull buffers at its own rate. Note that when the application does not
1289  * pull buffers fast enough, the queued buffers could consume a lot of memory,
1290  * especially when dealing with raw video frames.
1291  *
1292  * If an EOS event was received before any buffers, this function returns
1293  * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
1294  *
1295  * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
1296  *
1297  * Since: 0.10.22
1298  */
1299
1300 GstBuffer *
1301 gst_app_sink_pull_buffer (GstAppSink * appsink)
1302 {
1303   GST_DEBUG_OBJECT (appsink, "pull a buffer");
1304   return GST_BUFFER_CAST (gst_app_sink_pull_object (appsink));
1305 }
1306
1307 /**
1308  * gst_app_sink_pull_buffer_list:
1309  * @appsink: a #GstAppSink
1310  *
1311  * This function blocks until a buffer list or EOS becomes available or the
1312  * appsink element is set to the READY/NULL state.
1313  *
1314  * This function will only return buffer lists when the appsink is in the
1315  * PLAYING state. All rendered buffer lists will be put in a queue so that
1316  * the application can pull buffer lists at its own rate. Note that when
1317  * the application does not pull buffer lists fast enough, the queued buffer
1318  * lists could consume a lot of memory, especially when dealing with raw
1319  * video frames.
1320  *
1321  * If an EOS event was received before any buffer lists, this function returns
1322  * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
1323  *
1324  * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
1325  */
1326 GstBufferList *
1327 gst_app_sink_pull_buffer_list (GstAppSink * appsink)
1328 {
1329   GST_DEBUG_OBJECT (appsink, "pull a buffer list");
1330   return GST_BUFFER_LIST_CAST (gst_app_sink_pull_object (appsink));
1331 }
1332
1333 /**
1334  * gst_app_sink_set_callbacks:
1335  * @appsink: a #GstAppSink
1336  * @callbacks: the callbacks
1337  * @user_data: a user_data argument for the callbacks
1338  * @notify: a destroy notify function
1339  *
1340  * Set callbacks which will be executed for each new preroll, new buffer and eos.
1341  * This is an alternative to using the signals, it has lower overhead and is thus
1342  * less expensive, but also less flexible.
1343  *
1344  * If callbacks are installed, no signals will be emitted for performance
1345  * reasons.
1346  *
1347  * Since: 0.10.23
1348  */
1349 void
1350 gst_app_sink_set_callbacks (GstAppSink * appsink,
1351     GstAppSinkCallbacks * callbacks, gpointer user_data, GDestroyNotify notify)
1352 {
1353   GDestroyNotify old_notify;
1354   GstAppSinkPrivate *priv;
1355
1356   g_return_if_fail (GST_IS_APP_SINK (appsink));
1357   g_return_if_fail (callbacks != NULL);
1358
1359   priv = appsink->priv;
1360
1361   GST_OBJECT_LOCK (appsink);
1362   old_notify = priv->notify;
1363
1364   if (old_notify) {
1365     gpointer old_data;
1366
1367     old_data = priv->user_data;
1368
1369     priv->user_data = NULL;
1370     priv->notify = NULL;
1371     GST_OBJECT_UNLOCK (appsink);
1372
1373     old_notify (old_data);
1374
1375     GST_OBJECT_LOCK (appsink);
1376   }
1377   priv->callbacks = *callbacks;
1378   priv->user_data = user_data;
1379   priv->notify = notify;
1380   priv->buffer_lists_supported =
1381       gst_app_sink_check_buffer_lists_support (appsink);
1382   GST_OBJECT_UNLOCK (appsink);
1383 }
1384
1385 /*** GSTURIHANDLER INTERFACE *************************************************/
1386
1387 static GstURIType
1388 gst_app_sink_uri_get_type (void)
1389 {
1390   return GST_URI_SINK;
1391 }
1392
1393 static gchar **
1394 gst_app_sink_uri_get_protocols (void)
1395 {
1396   static gchar *protocols[] = { (char *) "appsink", NULL };
1397
1398   return protocols;
1399 }
1400
1401 static const gchar *
1402 gst_app_sink_uri_get_uri (GstURIHandler * handler)
1403 {
1404   return "appsink";
1405 }
1406
1407 static gboolean
1408 gst_app_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
1409 {
1410   gchar *protocol;
1411   gboolean ret;
1412
1413   protocol = gst_uri_get_protocol (uri);
1414   ret = !strcmp (protocol, "appsink");
1415   g_free (protocol);
1416
1417   return ret;
1418 }
1419
1420 static void
1421 gst_app_sink_uri_handler_init (gpointer g_iface, gpointer iface_data)
1422 {
1423   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
1424
1425   iface->get_type = gst_app_sink_uri_get_type;
1426   iface->get_protocols = gst_app_sink_uri_get_protocols;
1427   iface->get_uri = gst_app_sink_uri_get_uri;
1428   iface->set_uri = gst_app_sink_uri_set_uri;
1429 }