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