gst-libs/gst/app/gstappsink.*: Add more docs.
[platform/upstream/gstreamer.git] / gst-libs / gst / app / gstappsink.c
1 /* GStreamer
2  * Copyright (C) 2007 David Schleef <ds@schleef.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/gst.h>
25 #include <gst/base/gstbasesink.h>
26 #include <gst/gstbuffer.h>
27
28 #include <string.h>
29
30 #include "gstappsink.h"
31
32
33 GST_DEBUG_CATEGORY (app_sink_debug);
34 #define GST_CAT_DEFAULT app_sink_debug
35
36 static const GstElementDetails app_sink_details =
37 GST_ELEMENT_DETAILS ("AppSink",
38     "Generic/Sink",
39     "Allow the application to get access to raw buffer",
40     "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com");
41
42 enum
43 {
44   /* signals */
45   SIGNAL_EOS,
46   SIGNAL_NEW_PREROLL,
47   SIGNAL_NEW_BUFFER,
48
49   /* acions */
50   SIGNAL_PULL_PREROLL,
51   SIGNAL_PULL_BUFFER,
52
53   LAST_SIGNAL
54 };
55
56 #define DEFAULT_PROP_EOS                TRUE
57 #define DEFAULT_PROP_EMIT_SIGNALS       TRUE
58 #define DEFAULT_PROP_MAX_BUFFERS        0
59
60 enum
61 {
62   PROP_0,
63   PROP_CAPS,
64   PROP_EOS,
65   PROP_EMIT_SIGNALS,
66   PROP_MAX_BUFFERS,
67
68   PROP_LAST,
69 };
70
71 static GstStaticPadTemplate gst_app_sink_template =
72 GST_STATIC_PAD_TEMPLATE ("sink",
73     GST_PAD_SINK,
74     GST_PAD_ALWAYS,
75     GST_STATIC_CAPS_ANY);
76
77 static void gst_app_sink_dispose (GObject * object);
78 static void gst_app_sink_finalize (GObject * object);
79
80 static void gst_app_sink_set_property (GObject * object, guint prop_id,
81     const GValue * value, GParamSpec * pspec);
82 static void gst_app_sink_get_property (GObject * object, guint prop_id,
83     GValue * value, GParamSpec * pspec);
84
85 static gboolean gst_app_sink_start (GstBaseSink * psink);
86 static gboolean gst_app_sink_stop (GstBaseSink * psink);
87 static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
88 static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
89     GstBuffer * buffer);
90 static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
91     GstBuffer * buffer);
92 static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink);
93
94 static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
95
96 GST_BOILERPLATE (GstAppSink, gst_app_sink, GstBaseSink, GST_TYPE_BASE_SINK);
97
98 void
99 gst_app_marshal_OBJECT__VOID (GClosure * closure,
100     GValue * return_value,
101     guint n_param_values,
102     const GValue * param_values,
103     gpointer invocation_hint, gpointer marshal_data)
104 {
105   typedef GstBuffer *(*GMarshalFunc_OBJECT__VOID) (gpointer data1,
106       gpointer data2);
107   register GMarshalFunc_OBJECT__VOID callback;
108   register GCClosure *cc = (GCClosure *) closure;
109   register gpointer data1, data2;
110   GstBuffer *v_return;
111
112   g_return_if_fail (return_value != NULL);
113   g_return_if_fail (n_param_values == 1);
114
115   if (G_CCLOSURE_SWAP_DATA (closure)) {
116     data1 = closure->data;
117     data2 = g_value_peek_pointer (param_values + 0);
118   } else {
119     data1 = g_value_peek_pointer (param_values + 0);
120     data2 = closure->data;
121   }
122   callback =
123       (GMarshalFunc_OBJECT__VOID) (marshal_data ? marshal_data : cc->callback);
124
125   v_return = callback (data1, data2);
126
127   gst_value_take_buffer (return_value, v_return);
128 }
129
130 static void
131 gst_app_sink_base_init (gpointer g_class)
132 {
133   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
134
135   GST_DEBUG_CATEGORY_INIT (app_sink_debug, "appsink", 0, "appsink element");
136
137   gst_element_class_set_details (element_class, &app_sink_details);
138
139   gst_element_class_add_pad_template (element_class,
140       gst_static_pad_template_get (&gst_app_sink_template));
141 }
142
143 static void
144 gst_app_sink_class_init (GstAppSinkClass * klass)
145 {
146   GObjectClass *gobject_class = (GObjectClass *) klass;
147   GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
148
149   gobject_class->dispose = gst_app_sink_dispose;
150   gobject_class->finalize = gst_app_sink_finalize;
151
152   gobject_class->set_property = gst_app_sink_set_property;
153   gobject_class->get_property = gst_app_sink_get_property;
154
155   g_object_class_install_property (gobject_class, PROP_CAPS,
156       g_param_spec_boxed ("caps", "Caps",
157           "The caps of the sink pad", GST_TYPE_CAPS,
158           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
159
160   g_object_class_install_property (gobject_class, PROP_EOS,
161       g_param_spec_boolean ("eos", "EOS",
162           "Check if the sink is EOS or not started", DEFAULT_PROP_EOS,
163           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
164
165   g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
166       g_param_spec_boolean ("emit-signals", "Emit signals",
167           "Emit new-preroll and new-buffer signals", DEFAULT_PROP_EMIT_SIGNALS,
168           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
169
170   g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
171       g_param_spec_uint ("max-buffers", "Max Buffers",
172           "Control the maximum buffers to queue internally (0 = unlimited)",
173           0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
174           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
175
176   /**
177    * GstAppSink::eos:
178    * @appsink: the appsink element that emited the signal
179    *
180    * Signal that the end-of-stream has been reached. This signal is emited from
181    * the steaming thread.
182    */
183   gst_app_sink_signals[SIGNAL_EOS] =
184       g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
185       G_STRUCT_OFFSET (GstAppSinkClass, eos),
186       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
187   /**
188    * GstAppSink::new-preroll:
189    * @appsink: the appsink element that emited the signal
190    *
191    * Signal that a new preroll buffer is available. 
192    *
193    * This signal is emited from the steaming thread and only when the
194    * "emit-signals" property is %TRUE. 
195    *
196    * The new preroll buffer can be retrieved with the "pull-preroll" action
197    * signal or gst_app_sink_pull_preroll() either from this signal callback
198    * or from any other thread.
199    *
200    * Note that this signal is only emited when the "emit-signals" property is
201    * set to %TRUE, which it is not by default for performance reasons.
202    */
203   gst_app_sink_signals[SIGNAL_NEW_PREROLL] =
204       g_signal_new ("new-preroll", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
205       G_STRUCT_OFFSET (GstAppSinkClass, new_preroll),
206       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
207   /**
208    * GstAppSink::new-buffer:
209    * @appsink: the appsink element that emited the signal
210    *
211    * Signal that a new buffer is available.
212    *
213    * This signal is emited from the steaming thread and only when the
214    * "emit-signals" property is %TRUE. 
215    *
216    * The new preroll buffer can be retrieved with the "pull-buffer" action
217    * signal or gst_app_sink_pull_buffer() either from this signal callback
218    * or from any other thread.
219    *
220    * Note that this signal is only emited when the "emit-signals" property is
221    * set to %TRUE, which it is not by default for performance reasons.
222    */
223   gst_app_sink_signals[SIGNAL_NEW_BUFFER] =
224       g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
225       G_STRUCT_OFFSET (GstAppSinkClass, new_buffer),
226       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
227
228   /**
229    * GstAppSink::pull-preroll:
230    * @appsink: the appsink element to emit this signal on
231    *
232    * Get the last preroll buffer in @appsink. This was the buffer that caused the
233    * appsink to preroll in the PAUSED state. This buffer can be pulled many times
234    * and remains available to the application even after EOS.
235    *
236    * This function is typically used when dealing with a pipeline in the PAUSED
237    * state. Calling this function after doing a seek will give the buffer right
238    * after the seek position.
239    *
240    * Note that the preroll buffer will also be returned as the first buffer
241    * when calling gst_app_sink_pull_buffer() or the "pull-buffer" action signal.
242    *
243    * If an EOS event was received before any buffers, this function returns
244    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
245    *
246    * This function blocks until a preroll buffer or EOS is received or the appsink
247    * element is set to the READY/NULL state. 
248    *
249    * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
250    */
251   gst_app_sink_signals[SIGNAL_PULL_PREROLL] =
252       g_signal_new ("pull-preroll", G_TYPE_FROM_CLASS (klass),
253       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
254           pull_preroll), NULL, NULL, gst_app_marshal_OBJECT__VOID,
255       GST_TYPE_BUFFER, 0, G_TYPE_NONE);
256   /**
257    * GstAppSink::pull-buffer:
258    * @appsink: the appsink element to emit this signal on
259    *
260    * This function blocks until a buffer or EOS becomes available or the appsink
261    * element is set to the READY/NULL state. 
262    *
263    * This function will only return buffers when the appsink is in the PLAYING
264    * state. All rendered buffers will be put in a queue so that the application
265    * can pull buffers at its own rate. Note that when the application does not
266    * pull buffers fast enough, the queued buffers could consume a lot of memory,
267    * especially when dealing with raw video frames.
268    *
269    * If an EOS event was received before any buffers, this function returns
270    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
271    *
272    * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
273    */
274   gst_app_sink_signals[SIGNAL_PULL_PREROLL] =
275       g_signal_new ("pull-buffer", G_TYPE_FROM_CLASS (klass),
276       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
277           pull_buffer), NULL, NULL, gst_app_marshal_OBJECT__VOID,
278       GST_TYPE_BUFFER, 0, G_TYPE_NONE);
279
280   basesink_class->start = gst_app_sink_start;
281   basesink_class->stop = gst_app_sink_stop;
282   basesink_class->event = gst_app_sink_event;
283   basesink_class->preroll = gst_app_sink_preroll;
284   basesink_class->render = gst_app_sink_render;
285   basesink_class->get_caps = gst_app_sink_getcaps;
286
287   klass->pull_preroll = gst_app_sink_pull_preroll;
288   klass->pull_buffer = gst_app_sink_pull_buffer;
289 }
290
291 static void
292 gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass)
293 {
294   appsink->mutex = g_mutex_new ();
295   appsink->cond = g_cond_new ();
296   appsink->queue = g_queue_new ();
297
298   appsink->emit_signals = DEFAULT_PROP_EMIT_SIGNALS;
299   appsink->max_buffers = DEFAULT_PROP_MAX_BUFFERS;
300 }
301
302 static void
303 gst_app_sink_dispose (GObject * obj)
304 {
305   GstAppSink *appsink = GST_APP_SINK (obj);
306   GstBuffer *buffer;
307
308   if (appsink->caps) {
309     gst_caps_unref (appsink->caps);
310     appsink->caps = NULL;
311   }
312   if (appsink->preroll) {
313     gst_buffer_unref (appsink->preroll);
314     appsink->preroll = NULL;
315   }
316   g_mutex_lock (appsink->mutex);
317   while ((buffer = g_queue_pop_head (appsink->queue)))
318     gst_buffer_unref (buffer);
319   g_mutex_unlock (appsink->mutex);
320
321   G_OBJECT_CLASS (parent_class)->dispose (obj);
322 }
323
324 static void
325 gst_app_sink_finalize (GObject * obj)
326 {
327   GstAppSink *appsink = GST_APP_SINK (obj);
328
329   g_mutex_free (appsink->mutex);
330   g_cond_free (appsink->cond);
331   g_queue_free (appsink->queue);
332
333   G_OBJECT_CLASS (parent_class)->finalize (obj);
334 }
335
336 static void
337 gst_app_sink_set_property (GObject * object, guint prop_id,
338     const GValue * value, GParamSpec * pspec)
339 {
340   GstAppSink *appsink = GST_APP_SINK (object);
341
342   switch (prop_id) {
343     case PROP_CAPS:
344       gst_app_sink_set_caps (appsink, gst_value_get_caps (value));
345       break;
346     case PROP_EMIT_SIGNALS:
347       gst_app_sink_set_emit_signals (appsink, g_value_get_boolean (value));
348       break;
349     case PROP_MAX_BUFFERS:
350       gst_app_sink_set_max_buffers (appsink, g_value_get_uint (value));
351       break;
352     default:
353       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
354       break;
355   }
356 }
357
358 static void
359 gst_app_sink_get_property (GObject * object, guint prop_id, GValue * value,
360     GParamSpec * pspec)
361 {
362   GstAppSink *appsink = GST_APP_SINK (object);
363
364   switch (prop_id) {
365     case PROP_CAPS:
366     {
367       GstCaps *caps;
368
369       caps = gst_app_sink_get_caps (appsink);
370       gst_value_set_caps (value, caps);
371       if (caps)
372         gst_caps_unref (caps);
373       break;
374     }
375     case PROP_EOS:
376       g_value_set_boolean (value, gst_app_sink_is_eos (appsink));
377       break;
378     case PROP_EMIT_SIGNALS:
379       g_value_set_boolean (value, gst_app_sink_get_emit_signals (appsink));
380       break;
381     case PROP_MAX_BUFFERS:
382       g_value_set_uint (value, gst_app_sink_get_max_buffers (appsink));
383       break;
384     default:
385       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386       break;
387   }
388 }
389
390 static void
391 gst_app_sink_flush_unlocked (GstAppSink * appsink)
392 {
393   GstBuffer *buffer;
394
395   GST_DEBUG_OBJECT (appsink, "flushing appsink");
396   appsink->is_eos = FALSE;
397   gst_buffer_replace (&appsink->preroll, NULL);
398   while ((buffer = g_queue_pop_head (appsink->queue)))
399     gst_buffer_unref (buffer);
400   g_cond_signal (appsink->cond);
401 }
402
403 static gboolean
404 gst_app_sink_start (GstBaseSink * psink)
405 {
406   GstAppSink *appsink = GST_APP_SINK (psink);
407
408   g_mutex_lock (appsink->mutex);
409   appsink->is_eos = FALSE;
410   appsink->started = TRUE;
411   GST_DEBUG_OBJECT (appsink, "starting");
412   g_mutex_unlock (appsink->mutex);
413
414   return TRUE;
415 }
416
417 static gboolean
418 gst_app_sink_stop (GstBaseSink * psink)
419 {
420   GstAppSink *appsink = GST_APP_SINK (psink);
421
422   g_mutex_lock (appsink->mutex);
423   GST_DEBUG_OBJECT (appsink, "stopping");
424   appsink->started = FALSE;
425   gst_app_sink_flush_unlocked (appsink);
426   g_mutex_unlock (appsink->mutex);
427
428   return TRUE;
429 }
430
431 static gboolean
432 gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
433 {
434   GstAppSink *appsink = GST_APP_SINK (sink);
435
436   switch (event->type) {
437     case GST_EVENT_EOS:
438
439       g_mutex_lock (appsink->mutex);
440       GST_DEBUG_OBJECT (appsink, "receiving EOS");
441       appsink->is_eos = TRUE;
442       g_cond_signal (appsink->cond);
443       g_mutex_unlock (appsink->mutex);
444
445       /* emit EOS now */
446       g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_EOS], 0);
447       break;
448     case GST_EVENT_FLUSH_START:
449       break;
450     case GST_EVENT_FLUSH_STOP:
451       g_mutex_lock (appsink->mutex);
452       GST_DEBUG_OBJECT (appsink, "received FLUSH_STOP");
453       gst_app_sink_flush_unlocked (appsink);
454       g_mutex_unlock (appsink->mutex);
455       break;
456     default:
457       break;
458   }
459   return TRUE;
460 }
461
462 static GstFlowReturn
463 gst_app_sink_preroll (GstBaseSink * psink, GstBuffer * buffer)
464 {
465   GstAppSink *appsink = GST_APP_SINK (psink);
466   gboolean emit;
467
468   g_mutex_lock (appsink->mutex);
469   GST_DEBUG_OBJECT (appsink, "setting preroll buffer %p", buffer);
470   gst_buffer_replace (&appsink->preroll, buffer);
471   g_cond_signal (appsink->cond);
472   emit = appsink->emit_signals;
473   g_mutex_unlock (appsink->mutex);
474
475   if (emit)
476     g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_PREROLL], 0);
477
478   return GST_FLOW_OK;
479 }
480
481 static GstFlowReturn
482 gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
483 {
484   GstAppSink *appsink = GST_APP_SINK (psink);
485   gboolean emit;
486
487   g_mutex_lock (appsink->mutex);
488   GST_DEBUG_OBJECT (appsink, "pushing render buffer %p on queue", buffer);
489
490   while (appsink->max_buffers > 0 &&
491       appsink->queue->length >= appsink->max_buffers) {
492     /* FIXME, do proper unlocking when flushing */
493     g_cond_wait (appsink->cond, appsink->mutex);
494     if (!appsink->started)
495       goto not_started;
496   }
497   g_queue_push_tail (appsink->queue, gst_buffer_ref (buffer));
498   g_cond_signal (appsink->cond);
499   emit = appsink->emit_signals;
500   g_mutex_unlock (appsink->mutex);
501
502   if (emit)
503     g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
504
505   return GST_FLOW_OK;
506
507 not_started:
508   {
509     GST_DEBUG_OBJECT (appsink, "we stopped");
510     g_mutex_unlock (appsink->mutex);
511     return GST_FLOW_WRONG_STATE;
512   }
513 }
514
515 static GstCaps *
516 gst_app_sink_getcaps (GstBaseSink * psink)
517 {
518   GstCaps *caps;
519
520   GstAppSink *appsink = GST_APP_SINK (psink);
521
522   GST_OBJECT_LOCK (appsink);
523   if ((caps = appsink->caps))
524     gst_caps_ref (caps);
525   GST_DEBUG_OBJECT (appsink, "got caps %" GST_PTR_FORMAT, caps);
526   GST_OBJECT_UNLOCK (appsink);
527
528   return caps;
529 }
530
531 /* external API */
532
533 /**
534  * gst_app_sink_set_caps:
535  * @appsink: a #GstAppSink
536  * @caps: caps to set
537  *
538  * Set the capabilities on the appsink element.  This function takes
539  * a copy of the caps structure. After calling this method, the sink will only
540  * accept caps that match @caps. If @caps is non-fixed, you must check the caps
541  * on the buffers to get the actual used caps. 
542  */
543 void
544 gst_app_sink_set_caps (GstAppSink * appsink, const GstCaps * caps)
545 {
546   GstCaps *old;
547
548   g_return_if_fail (appsink != NULL);
549   g_return_if_fail (GST_IS_APP_SINK (appsink));
550
551   GST_OBJECT_LOCK (appsink);
552   GST_DEBUG_OBJECT (appsink, "setting caps to %" GST_PTR_FORMAT, caps);
553   old = appsink->caps;
554   if (caps)
555     appsink->caps = gst_caps_copy (caps);
556   else
557     appsink->caps = NULL;
558   if (old)
559     gst_caps_unref (old);
560   GST_OBJECT_UNLOCK (appsink);
561 }
562
563 /**
564  * gst_app_sink_get_caps:
565  * @appsink: a #GstAppSink
566  *
567  * Get the configured caps on @appsink.
568  *
569  * Returns: the #GstCaps accepted by the sink. gst_caps_unref() after usage.
570  */
571 GstCaps *
572 gst_app_sink_get_caps (GstAppSink * appsink)
573 {
574   GstCaps *caps;
575
576   g_return_val_if_fail (appsink != NULL, NULL);
577   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
578
579   GST_OBJECT_LOCK (appsink);
580   if ((caps = appsink->caps))
581     gst_caps_ref (caps);
582   GST_DEBUG_OBJECT (appsink, "getting caps of %" GST_PTR_FORMAT, caps);
583   GST_OBJECT_UNLOCK (appsink);
584
585   return caps;
586 }
587
588 /**
589  * gst_app_sink_is_eos:
590  * @appsink: a #GstAppSink
591  *
592  * Check if @appsink is EOS, which is when no more buffers can be pulled because
593  * an EOS event was received.
594  *
595  * This function also returns %TRUE when the appsink is not in the PAUSED or
596  * PLAYING state.
597  *
598  * Returns: %TRUE if no more buffers can be pulled and the appsink is EOS.
599  */
600 gboolean
601 gst_app_sink_is_eos (GstAppSink * appsink)
602 {
603   gboolean ret;
604
605   g_return_val_if_fail (appsink != NULL, FALSE);
606   g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
607
608   g_mutex_lock (appsink->mutex);
609   if (!appsink->started)
610     goto not_started;
611
612   if (appsink->is_eos && g_queue_is_empty (appsink->queue)) {
613     GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty");
614     ret = TRUE;
615   } else {
616     GST_DEBUG_OBJECT (appsink, "we are not yet EOS");
617     ret = FALSE;
618   }
619   g_mutex_unlock (appsink->mutex);
620
621   return ret;
622
623 not_started:
624   {
625     GST_DEBUG_OBJECT (appsink, "we are stopped, return TRUE");
626     g_mutex_unlock (appsink->mutex);
627     return TRUE;
628   }
629 }
630
631 /**
632  * gst_app_sink_set_emit_signals:
633  * @appsink: a #GstAppSink
634  * @emit: the new state
635  *
636  * Make appsink emit the "new-preroll" and "new-buffer" signals. This option is
637  * by default disabled because signal emission is expensive and unneeded when
638  * the application prefers to operate in pull mode.
639  */
640 void
641 gst_app_sink_set_emit_signals (GstAppSink * appsink, gboolean emit)
642 {
643   g_return_if_fail (GST_IS_APP_SINK (appsink));
644
645   g_mutex_lock (appsink->mutex);
646   appsink->emit_signals = emit;
647   g_mutex_unlock (appsink->mutex);
648 }
649
650 /**
651  * gst_app_sink_get_emit_signals:
652  * @appsink: a #GstAppSink
653  *
654  * Check if appsink will emit the "new-preroll" and "new-buffer" signals.
655  *
656  * Returns: %TRUE if @appsink is emiting the "new-preroll" and "new-buffer"
657  * signals.
658  */
659 gboolean
660 gst_app_sink_get_emit_signals (GstAppSink * appsink)
661 {
662   gboolean result;
663
664   g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE);
665
666   g_mutex_lock (appsink->mutex);
667   result = appsink->emit_signals;
668   g_mutex_unlock (appsink->mutex);
669
670   return result;
671 }
672
673 /**
674  * gst_app_sink_set_max_buffers:
675  * @appsink: a #GstAppSink
676  * @max: the maximum number of buffers to queue
677  *
678  * Set the maximum amount of buffers that can be queued in @appsink. After this
679  * amount of buffers are queued in appsink, any more buffers will block upstream
680  * elements until a buffer is pulled from @appsink.
681  */
682 void
683 gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max)
684 {
685   g_return_if_fail (GST_IS_APP_SINK (appsink));
686
687   g_mutex_lock (appsink->mutex);
688   if (max != appsink->max_buffers) {
689     appsink->max_buffers = max;
690     /* signal the change */
691     g_cond_signal (appsink->cond);
692   }
693   g_mutex_unlock (appsink->mutex);
694 }
695
696 /**
697  * gst_app_sink_get_max_buffers:
698  * @appsink: a #GstAppSink
699  *
700  * Get the maximum amount of buffers that can be queued in @appsink.
701  *
702  * Returns: The maximum amount of buffers that can be queued.
703  */
704 guint
705 gst_app_sink_get_max_buffers (GstAppSink * appsink)
706 {
707   guint result;
708
709   g_return_val_if_fail (GST_IS_APP_SINK (appsink), 0);
710
711   g_mutex_lock (appsink->mutex);
712   result = appsink->max_buffers;
713   g_mutex_unlock (appsink->mutex);
714
715   return result;
716 }
717
718 /**
719  * gst_app_sink_pull_preroll:
720  * @appsink: a #GstAppSink
721  *
722  * Get the last preroll buffer in @appsink. This was the buffer that caused the
723  * appsink to preroll in the PAUSED state. This buffer can be pulled many times
724  * and remains available to the application even after EOS.
725  *
726  * This function is typically used when dealing with a pipeline in the PAUSED
727  * state. Calling this function after doing a seek will give the buffer right
728  * after the seek position.
729  *
730  * Note that the preroll buffer will also be returned as the first buffer
731  * when calling gst_app_sink_pull_buffer().
732  *
733  * If an EOS event was received before any buffers, this function returns
734  * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
735  *
736  * This function blocks until a preroll buffer or EOS is received or the appsink
737  * element is set to the READY/NULL state. 
738  *
739  * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
740  */
741 GstBuffer *
742 gst_app_sink_pull_preroll (GstAppSink * appsink)
743 {
744   GstBuffer *buf = NULL;
745
746   g_return_val_if_fail (appsink != NULL, NULL);
747   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
748
749   g_mutex_lock (appsink->mutex);
750
751   while (TRUE) {
752     GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
753     if (!appsink->started)
754       goto not_started;
755
756     if (appsink->preroll != NULL)
757       break;
758
759     if (appsink->is_eos)
760       goto eos;
761
762     /* nothing to return, wait */
763     GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer");
764     g_cond_wait (appsink->cond, appsink->mutex);
765   }
766   buf = gst_buffer_ref (appsink->preroll);
767   GST_DEBUG_OBJECT (appsink, "we have the preroll buffer %p", buf);
768   g_mutex_unlock (appsink->mutex);
769
770   return buf;
771
772   /* special conditions */
773 eos:
774   {
775     GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
776     g_mutex_unlock (appsink->mutex);
777     return NULL;
778   }
779 not_started:
780   {
781     GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
782     g_mutex_unlock (appsink->mutex);
783     return NULL;
784   }
785 }
786
787 /**
788  * gst_app_sink_pull_buffer:
789  * @appsink: a #GstAppSink
790  *
791  * This function blocks until a buffer or EOS becomes available or the appsink
792  * element is set to the READY/NULL state. 
793  *
794  * This function will only return buffers when the appsink is in the PLAYING
795  * state. All rendered buffers will be put in a queue so that the application
796  * can pull buffers at its own rate. Note that when the application does not
797  * pull buffers fast enough, the queued buffers could consume a lot of memory,
798  * especially when dealing with raw video frames.
799  *
800  * If an EOS event was received before any buffers, this function returns
801  * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
802  *
803  * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
804  */
805 GstBuffer *
806 gst_app_sink_pull_buffer (GstAppSink * appsink)
807 {
808   GstBuffer *buf = NULL;
809
810   g_return_val_if_fail (appsink != NULL, NULL);
811   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
812
813   g_mutex_lock (appsink->mutex);
814
815   while (TRUE) {
816     GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
817     if (!appsink->started)
818       goto not_started;
819
820     if (!g_queue_is_empty (appsink->queue))
821       break;
822
823     if (appsink->is_eos)
824       goto eos;
825
826     /* nothing to return, wait */
827     GST_DEBUG_OBJECT (appsink, "waiting for a buffer");
828     g_cond_wait (appsink->cond, appsink->mutex);
829   }
830   buf = g_queue_pop_head (appsink->queue);
831   GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buf);
832   g_cond_signal (appsink->cond);
833   g_mutex_unlock (appsink->mutex);
834
835   return buf;
836
837   /* special conditions */
838 eos:
839   {
840     GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
841     g_mutex_unlock (appsink->mutex);
842     return NULL;
843   }
844 not_started:
845   {
846     GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
847     g_mutex_unlock (appsink->mutex);
848     return NULL;
849   }
850 }