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