gst_plugins_base/gst-libs/gst/app/gstappsink.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    82 #endif
    82 #endif
    83 
    83 
    84 #include <gst/gst.h>
    84 #include <gst/gst.h>
    85 #include <gst/base/gstbasesink.h>
    85 #include <gst/base/gstbasesink.h>
    86 #include <gst/gstbuffer.h>
    86 #include <gst/gstbuffer.h>
    87 #include <gst/gstbufferlist.h>
       
    88 
    87 
    89 #include <string.h>
    88 #include <string.h>
    90 
    89 
    91 #include "gstappsink.h"
    90 #include "gstappsink.h"
    92 
    91 #ifdef __SYMBIAN32__
       
    92 #include <glib_global.h>
       
    93 #endif
    93 struct _GstAppSinkPrivate
    94 struct _GstAppSinkPrivate
    94 {
    95 {
    95   GstCaps *caps;
    96   GstCaps *caps;
    96   gboolean emit_signals;
    97   gboolean emit_signals;
    97   guint max_buffers;
    98   guint max_buffers;
   117 {
   118 {
   118   /* signals */
   119   /* signals */
   119   SIGNAL_EOS,
   120   SIGNAL_EOS,
   120   SIGNAL_NEW_PREROLL,
   121   SIGNAL_NEW_PREROLL,
   121   SIGNAL_NEW_BUFFER,
   122   SIGNAL_NEW_BUFFER,
   122   SIGNAL_NEW_BUFFER_LIST,
       
   123 
   123 
   124   /* actions */
   124   /* actions */
   125   SIGNAL_PULL_PREROLL,
   125   SIGNAL_PULL_PREROLL,
   126   SIGNAL_PULL_BUFFER,
   126   SIGNAL_PULL_BUFFER,
   127   SIGNAL_PULL_BUFFER_LIST,
       
   128 
   127 
   129   LAST_SIGNAL
   128   LAST_SIGNAL
   130 };
   129 };
   131 
   130 
   132 #define DEFAULT_PROP_EOS		TRUE
   131 #define DEFAULT_PROP_EOS		TRUE
   160 #ifdef __SYMBIAN32__
   159 #ifdef __SYMBIAN32__
   161 static void gst_app_sink_class_init (GstAppSinkClass * klass);
   160 static void gst_app_sink_class_init (GstAppSinkClass * klass);
   162 static void gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass);
   161 static void gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass);
   163 static void gst_app_sink_base_init (gpointer g_class);
   162 static void gst_app_sink_base_init (gpointer g_class);
   164 #endif
   163 #endif
       
   164 
   165 static void gst_app_sink_set_property (GObject * object, guint prop_id,
   165 static void gst_app_sink_set_property (GObject * object, guint prop_id,
   166     const GValue * value, GParamSpec * pspec);
   166     const GValue * value, GParamSpec * pspec);
   167 static void gst_app_sink_get_property (GObject * object, guint prop_id,
   167 static void gst_app_sink_get_property (GObject * object, guint prop_id,
   168     GValue * value, GParamSpec * pspec);
   168     GValue * value, GParamSpec * pspec);
   169 
   169 
   172 static gboolean gst_app_sink_start (GstBaseSink * psink);
   172 static gboolean gst_app_sink_start (GstBaseSink * psink);
   173 static gboolean gst_app_sink_stop (GstBaseSink * psink);
   173 static gboolean gst_app_sink_stop (GstBaseSink * psink);
   174 static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
   174 static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
   175 static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
   175 static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
   176     GstBuffer * buffer);
   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,
   177 static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
   180     GstBuffer * buffer);
   178     GstBuffer * buffer);
   181 static GstFlowReturn gst_app_sink_render_list (GstBaseSink * psink,
       
   182     GstBufferList * list);
       
   183 static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink);
   179 static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink);
   184 static GstMiniObject *gst_app_sink_pull_object (GstAppSink * appsink);
       
   185 
   180 
   186 static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
   181 static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
   187 
   182 
   188 static void
   183 static void
   189 _do_init (GType filesrc_type)
   184 _do_init (GType filesrc_type)
   207 {                                   
   202 {                                   
   208   parent_class = (GstBaseSinkClass *)               
   203   parent_class = (GstBaseSinkClass *)               
   209       g_type_class_peek_parent (g_class);              
   204       g_type_class_peek_parent (g_class);              
   210       gst_app_sink_class_init ((GstAppSinkClass *)g_class);       
   205       gst_app_sink_class_init ((GstAppSinkClass *)g_class);       
   211 }
   206 }
       
   207 
   212 EXPORT_C GType
   208 EXPORT_C GType
   213 gst_app_sink_get_type (void)
   209 gst_app_sink_get_type (void)
   214 {
   210 {
   215 static GType object_type = 0;                      
   211 static GType object_type = 0;                      
   216  if (G_UNLIKELY (object_type == 0)) {                  
   212  if (G_UNLIKELY (object_type == 0)) {                  
   294   gobject_class->get_property = gst_app_sink_get_property;
   290   gobject_class->get_property = gst_app_sink_get_property;
   295 
   291 
   296   g_object_class_install_property (gobject_class, PROP_CAPS,
   292   g_object_class_install_property (gobject_class, PROP_CAPS,
   297       g_param_spec_boxed ("caps", "Caps",
   293       g_param_spec_boxed ("caps", "Caps",
   298           "The allowed caps for the sink pad", GST_TYPE_CAPS,
   294           "The allowed caps for the sink pad", GST_TYPE_CAPS,
   299           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   295           G_PARAM_READWRITE));
   300 
   296 
   301   g_object_class_install_property (gobject_class, PROP_EOS,
   297   g_object_class_install_property (gobject_class, PROP_EOS,
   302       g_param_spec_boolean ("eos", "EOS",
   298       g_param_spec_boolean ("eos", "EOS",
   303           "Check if the sink is EOS or not started", DEFAULT_PROP_EOS,
   299           "Check if the sink is EOS or not started", DEFAULT_PROP_EOS,
   304           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   300           G_PARAM_READABLE));
   305 
   301 
   306   g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
   302   g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS,
   307       g_param_spec_boolean ("emit-signals", "Emit signals",
   303       g_param_spec_boolean ("emit-signals", "Emit signals",
   308           "Emit new-preroll and new-buffer signals", DEFAULT_PROP_EMIT_SIGNALS,
   304           "Emit new-preroll and new-buffer signals", DEFAULT_PROP_EMIT_SIGNALS,
   309           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   305           G_PARAM_READWRITE));
   310 
   306 
   311   g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
   307   g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
   312       g_param_spec_uint ("max-buffers", "Max Buffers",
   308       g_param_spec_uint ("max-buffers", "Max Buffers",
   313           "The maximum number of buffers to queue internally (0 = unlimited)",
   309           "The maximum number of buffers to queue internally (0 = unlimited)",
   314           0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
   310           0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
   315           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   311           G_PARAM_READWRITE));
   316 
   312 
   317   g_object_class_install_property (gobject_class, PROP_DROP,
   313   g_object_class_install_property (gobject_class, PROP_DROP,
   318       g_param_spec_boolean ("drop", "Drop",
   314       g_param_spec_boolean ("drop", "Drop",
   319           "Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
   315           "Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP,
   320           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   316           G_PARAM_READWRITE));
   321 
   317 
   322   /**
   318   /**
   323    * GstAppSink::eos:
   319    * GstAppSink::eos:
   324    * @appsink: the appsink element that emited the signal
   320    * @appsink: the appsink element that emited the signal
   325    *
   321    *
   368    */
   364    */
   369   gst_app_sink_signals[SIGNAL_NEW_BUFFER] =
   365   gst_app_sink_signals[SIGNAL_NEW_BUFFER] =
   370       g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
   366       g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
   371       G_STRUCT_OFFSET (GstAppSinkClass, new_buffer),
   367       G_STRUCT_OFFSET (GstAppSinkClass, new_buffer),
   372       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   368       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   373   /**
       
   374    * GstAppSink::new-buffer-list:
       
   375    * @appsink: the appsink element that emited the signal
       
   376    *
       
   377    * Signal that a new bufferlist is available.
       
   378    *
       
   379    * This signal is emited from the steaming thread and only when the
       
   380    * "emit-signals" property is %TRUE. 
       
   381    *
       
   382    * The new buffer can be retrieved with the "pull-buffer-list" action
       
   383    * signal or gst_app_sink_pull_buffe_listr() either from this signal callback
       
   384    * or from any other thread.
       
   385    *
       
   386    * Note that this signal is only emited when the "emit-signals" property is
       
   387    * set to %TRUE, which it is not by default for performance reasons.
       
   388    */
       
   389   gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST] =
       
   390       g_signal_new ("new-buffer-list", G_TYPE_FROM_CLASS (klass),
       
   391       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, new_buffer_list),
       
   392       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
       
   393 
   369 
   394   /**
   370   /**
   395    * GstAppSink::pull-preroll:
   371    * GstAppSink::pull-preroll:
   396    * @appsink: the appsink element to emit this signal on
   372    * @appsink: the appsink element to emit this signal on
   397    *
   373    *
   443   gst_app_sink_signals[SIGNAL_PULL_BUFFER] =
   419   gst_app_sink_signals[SIGNAL_PULL_BUFFER] =
   444       g_signal_new ("pull-buffer", G_TYPE_FROM_CLASS (klass),
   420       g_signal_new ("pull-buffer", G_TYPE_FROM_CLASS (klass),
   445       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
   421       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
   446           pull_buffer), NULL, NULL, gst_app_marshal_BUFFER__VOID,
   422           pull_buffer), NULL, NULL, gst_app_marshal_BUFFER__VOID,
   447       GST_TYPE_BUFFER, 0, G_TYPE_NONE);
   423       GST_TYPE_BUFFER, 0, G_TYPE_NONE);
   448   /**
       
   449    * GstAppSink::pull-buffer-list:
       
   450    * @appsink: the appsink element to emit this signal on
       
   451    *
       
   452    * This function blocks until a buffer list or EOS becomes available or the appsink
       
   453    * element is set to the READY/NULL state. 
       
   454    *
       
   455    * This function will only return bufferlists when the appsink is in the PLAYING
       
   456    * state. All rendered bufferlists will be put in a queue so that the application
       
   457    * can pull bufferlists at its own rate. 
       
   458    *
       
   459    * Note that when the application does not pull bufferlists fast enough, the
       
   460    * queued bufferlists could consume a lot of memory, especially when dealing with
       
   461    * raw video frames. It's possible to control the behaviour of the queue with
       
   462    * the "drop" and "max-buffers" properties.
       
   463    *
       
   464    * If an EOS event was received before any buffers, this function returns
       
   465    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
       
   466    *
       
   467    * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
       
   468    */
       
   469   gst_app_sink_signals[SIGNAL_PULL_BUFFER_LIST] =
       
   470       g_signal_new ("pull-buffer-list", G_TYPE_FROM_CLASS (klass),
       
   471       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
       
   472           pull_buffer_list), NULL, NULL, gst_app_marshal_BUFFER__VOID,
       
   473       GST_TYPE_BUFFER_LIST, 0, G_TYPE_NONE);
       
   474 
   424 
   475   basesink_class->unlock = gst_app_sink_unlock_start;
   425   basesink_class->unlock = gst_app_sink_unlock_start;
   476   basesink_class->unlock_stop = gst_app_sink_unlock_stop;
   426   basesink_class->unlock_stop = gst_app_sink_unlock_stop;
   477   basesink_class->start = gst_app_sink_start;
   427   basesink_class->start = gst_app_sink_start;
   478   basesink_class->stop = gst_app_sink_stop;
   428   basesink_class->stop = gst_app_sink_stop;
   479   basesink_class->event = gst_app_sink_event;
   429   basesink_class->event = gst_app_sink_event;
   480   basesink_class->preroll = gst_app_sink_preroll;
   430   basesink_class->preroll = gst_app_sink_preroll;
   481   basesink_class->render = gst_app_sink_render;
   431   basesink_class->render = gst_app_sink_render;
   482   basesink_class->render_list = gst_app_sink_render_list;
       
   483   basesink_class->get_caps = gst_app_sink_getcaps;
   432   basesink_class->get_caps = gst_app_sink_getcaps;
   484 
   433 
   485   klass->pull_preroll = gst_app_sink_pull_preroll;
   434   klass->pull_preroll = gst_app_sink_pull_preroll;
   486   klass->pull_buffer = gst_app_sink_pull_buffer;
   435   klass->pull_buffer = gst_app_sink_pull_buffer;
   487   klass->pull_buffer_list = gst_app_sink_pull_buffer_list;
       
   488 
   436 
   489   g_type_class_add_private (klass, sizeof (GstAppSinkPrivate));
   437   g_type_class_add_private (klass, sizeof (GstAppSinkPrivate));
   490 }
   438 }
   491 
   439 
   492 static void
   440 static void
   506 
   454 
   507 static void
   455 static void
   508 gst_app_sink_dispose (GObject * obj)
   456 gst_app_sink_dispose (GObject * obj)
   509 {
   457 {
   510   GstAppSink *appsink = GST_APP_SINK (obj);
   458   GstAppSink *appsink = GST_APP_SINK (obj);
   511   GstMiniObject *queue_obj;
   459   GstBuffer *buffer;
   512 
   460 
   513   GST_OBJECT_LOCK (appsink);
   461   GST_OBJECT_LOCK (appsink);
   514   if (appsink->priv->caps) {
   462   if (appsink->priv->caps) {
   515     gst_caps_unref (appsink->priv->caps);
   463     gst_caps_unref (appsink->priv->caps);
   516     appsink->priv->caps = NULL;
   464     appsink->priv->caps = NULL;
   526   g_mutex_lock (appsink->priv->mutex);
   474   g_mutex_lock (appsink->priv->mutex);
   527   if (appsink->priv->preroll) {
   475   if (appsink->priv->preroll) {
   528     gst_buffer_unref (appsink->priv->preroll);
   476     gst_buffer_unref (appsink->priv->preroll);
   529     appsink->priv->preroll = NULL;
   477     appsink->priv->preroll = NULL;
   530   }
   478   }
   531   while ((queue_obj = g_queue_pop_head (appsink->priv->queue)))
   479   while ((buffer = g_queue_pop_head (appsink->priv->queue)))
   532     gst_mini_object_unref (queue_obj);
   480     gst_buffer_unref (buffer);
   533   g_mutex_unlock (appsink->priv->mutex);
   481   g_mutex_unlock (appsink->priv->mutex);
   534 
   482 
   535   G_OBJECT_CLASS (parent_class)->dispose (obj);
   483   G_OBJECT_CLASS (parent_class)->dispose (obj);
   536 }
   484 }
   537 
   485 
   636 }
   584 }
   637 
   585 
   638 static void
   586 static void
   639 gst_app_sink_flush_unlocked (GstAppSink * appsink)
   587 gst_app_sink_flush_unlocked (GstAppSink * appsink)
   640 {
   588 {
   641   GstMiniObject *obj;
   589   GstBuffer *buffer;
   642 
   590 
   643   GST_DEBUG_OBJECT (appsink, "flush stop appsink");
   591   GST_DEBUG_OBJECT (appsink, "flush stop appsink");
   644   appsink->priv->is_eos = FALSE;
   592   appsink->priv->is_eos = FALSE;
   645   gst_buffer_replace (&appsink->priv->preroll, NULL);
   593   gst_buffer_replace (&appsink->priv->preroll, NULL);
   646   while ((obj = g_queue_pop_head (appsink->priv->queue)))
   594   while ((buffer = g_queue_pop_head (appsink->priv->queue)))
   647     gst_mini_object_unref (obj);
   595     gst_buffer_unref (buffer);
   648   g_cond_signal (appsink->priv->cond);
   596   g_cond_signal (appsink->priv->cond);
   649 }
   597 }
   650 
   598 
   651 static gboolean
   599 static gboolean
   652 gst_app_sink_start (GstBaseSink * psink)
   600 gst_app_sink_start (GstBaseSink * psink)
   748     return GST_FLOW_WRONG_STATE;
   696     return GST_FLOW_WRONG_STATE;
   749   }
   697   }
   750 }
   698 }
   751 
   699 
   752 static GstFlowReturn
   700 static GstFlowReturn
   753 gst_app_sink_render_common (GstBaseSink * psink, GstMiniObject * data,
   701 gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
   754     gboolean is_list)
   702 {
   755 {
   703   GstFlowReturn res = GST_FLOW_OK;
   756   GstAppSink *appsink = GST_APP_SINK (psink);
   704   GstAppSink *appsink = GST_APP_SINK (psink);
   757   gboolean emit;
   705   gboolean emit;
   758 
   706 
   759   g_mutex_lock (appsink->priv->mutex);
   707   g_mutex_lock (appsink->priv->mutex);
   760   if (appsink->priv->flushing)
   708   if (appsink->priv->flushing)
   761     goto flushing;
   709     goto flushing;
   762 
   710 
   763   GST_DEBUG_OBJECT (appsink, "pushing render buffer%s %p on queue (%d)",
   711   GST_DEBUG_OBJECT (appsink, "pushing render buffer %p on queue (%d)",
   764       is_list ? " list" : "", data, appsink->priv->queue->length);
   712       buffer, appsink->priv->queue->length);
   765 
   713 
   766   while (appsink->priv->max_buffers > 0 &&
   714   while (appsink->priv->max_buffers > 0 &&
   767       appsink->priv->queue->length >= appsink->priv->max_buffers) {
   715       appsink->priv->queue->length >= appsink->priv->max_buffers) {
   768     if (appsink->priv->drop) {
   716     if (appsink->priv->drop) {
   769       GstMiniObject *obj;
   717       GstBuffer *buf;
   770 
   718 
   771       /* we need to drop the oldest buffer/list and try again */
   719       /* we need to drop the oldest buffer and try again */
   772       obj = g_queue_pop_head (appsink->priv->queue);
   720       buf = g_queue_pop_head (appsink->priv->queue);
   773       GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", obj);
   721       GST_DEBUG_OBJECT (appsink, "dropping old buffer %p", buf);
   774       gst_mini_object_unref (obj);
   722       gst_buffer_unref (buf);
   775     } else {
   723     } else {
   776       GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
   724       GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
   777           appsink->priv->queue->length, appsink->priv->max_buffers);
   725           appsink->priv->queue->length, appsink->priv->max_buffers);
   778       /* wait for a buffer to be removed or flush */
   726       /* wait for a buffer to be removed or flush */
   779       g_cond_wait (appsink->priv->cond, appsink->priv->mutex);
   727       g_cond_wait (appsink->priv->cond, appsink->priv->mutex);
   780       if (appsink->priv->flushing)
   728       if (appsink->priv->flushing)
   781         goto flushing;
   729         goto flushing;
   782     }
   730     }
   783   }
   731   }
   784   /* we need to ref the buffer when pushing it in the queue */
   732   /* we need to ref the buffer when pushing it in the queue */
   785   g_queue_push_tail (appsink->priv->queue, gst_mini_object_ref (data));
   733   g_queue_push_tail (appsink->priv->queue, gst_buffer_ref (buffer));
       
   734 
   786   g_cond_signal (appsink->priv->cond);
   735   g_cond_signal (appsink->priv->cond);
   787   emit = appsink->priv->emit_signals;
   736   emit = appsink->priv->emit_signals;
   788   g_mutex_unlock (appsink->priv->mutex);
   737   g_mutex_unlock (appsink->priv->mutex);
   789 
   738 
   790   if (is_list) {
   739   if (appsink->priv->callbacks.new_buffer)
   791     if (appsink->priv->callbacks.new_buffer_list)
   740     res =
   792       appsink->priv->callbacks.new_buffer_list (appsink,
   741         appsink->priv->callbacks.new_buffer (appsink, appsink->priv->user_data);
   793           appsink->priv->user_data);
   742   else if (emit)
   794   } else {
   743     g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
   795     if (appsink->priv->callbacks.new_buffer)
   744 
   796       appsink->priv->callbacks.new_buffer (appsink, appsink->priv->user_data);
   745   return res;
   797     else if (emit)
       
   798       g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
       
   799   }
       
   800   return GST_FLOW_OK;
       
   801 
   746 
   802 flushing:
   747 flushing:
   803   {
   748   {
   804     GST_DEBUG_OBJECT (appsink, "we are flushing");
   749     GST_DEBUG_OBJECT (appsink, "we are flushing");
   805     g_mutex_unlock (appsink->priv->mutex);
   750     g_mutex_unlock (appsink->priv->mutex);
   806     return GST_FLOW_WRONG_STATE;
   751     return GST_FLOW_WRONG_STATE;
   807   }
   752   }
   808 }
   753 }
   809 
   754 
   810 static GstFlowReturn
       
   811 gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
       
   812 {
       
   813   return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (buffer),
       
   814       FALSE);
       
   815 }
       
   816 
       
   817 static GstFlowReturn
       
   818 gst_app_sink_render_list (GstBaseSink * psink, GstBufferList * list)
       
   819 {
       
   820   return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (list), TRUE);
       
   821 }
       
   822 
       
   823 static GstCaps *
   755 static GstCaps *
   824 gst_app_sink_getcaps (GstBaseSink * psink)
   756 gst_app_sink_getcaps (GstBaseSink * psink)
   825 {
   757 {
   826   GstCaps *caps;
   758   GstCaps *caps;
   827 
   759 
   832     gst_caps_ref (caps);
   764     gst_caps_ref (caps);
   833   GST_DEBUG_OBJECT (appsink, "got caps %" GST_PTR_FORMAT, caps);
   765   GST_DEBUG_OBJECT (appsink, "got caps %" GST_PTR_FORMAT, caps);
   834   GST_OBJECT_UNLOCK (appsink);
   766   GST_OBJECT_UNLOCK (appsink);
   835 
   767 
   836   return caps;
   768   return caps;
   837 }
       
   838 
       
   839 static GstMiniObject *
       
   840 gst_app_sink_pull_object (GstAppSink * appsink)
       
   841 {
       
   842   GstMiniObject *obj = NULL;
       
   843 
       
   844   g_return_val_if_fail (appsink != NULL, NULL);
       
   845   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
       
   846 
       
   847   g_mutex_lock (appsink->priv->mutex);
       
   848 
       
   849   while (TRUE) {
       
   850     GST_DEBUG_OBJECT (appsink, "trying to grab a buffer/list");
       
   851     if (!appsink->priv->started)
       
   852       goto not_started;
       
   853 
       
   854     if (!g_queue_is_empty (appsink->priv->queue))
       
   855       break;
       
   856 
       
   857     if (appsink->priv->is_eos)
       
   858       goto eos;
       
   859 
       
   860     /* nothing to return, wait */
       
   861     GST_DEBUG_OBJECT (appsink, "waiting for a buffer/list");
       
   862     g_cond_wait (appsink->priv->cond, appsink->priv->mutex);
       
   863   }
       
   864   obj = g_queue_pop_head (appsink->priv->queue);
       
   865   GST_DEBUG_OBJECT (appsink, "we have a buffer/list %p", obj);
       
   866   g_cond_signal (appsink->priv->cond);
       
   867   g_mutex_unlock (appsink->priv->mutex);
       
   868 
       
   869   return obj;
       
   870 
       
   871   /* special conditions */
       
   872 eos:
       
   873   {
       
   874     GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
       
   875     g_mutex_unlock (appsink->priv->mutex);
       
   876     return NULL;
       
   877   }
       
   878 not_started:
       
   879   {
       
   880     GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
       
   881     g_mutex_unlock (appsink->priv->mutex);
       
   882     return NULL;
       
   883   }
       
   884 }
   769 }
   885 
   770 
   886 /* external API */
   771 /* external API */
   887 
   772 
   888 /**
   773 /**
  1224  *
  1109  *
  1225  * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
  1110  * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
  1226  *
  1111  *
  1227  * Since: 0.10.22
  1112  * Since: 0.10.22
  1228  */
  1113  */
  1229 
       
  1230 EXPORT_C GstBuffer *
  1114 EXPORT_C GstBuffer *
  1231 gst_app_sink_pull_buffer (GstAppSink * appsink)
  1115 gst_app_sink_pull_buffer (GstAppSink * appsink)
  1232 {
  1116 {
  1233   GST_DEBUG_OBJECT (appsink, "pull a buffer");
  1117   GstBuffer *buf = NULL;
  1234   return GST_BUFFER_CAST (gst_app_sink_pull_object (appsink));
  1118 
  1235 }
  1119   g_return_val_if_fail (appsink != NULL, NULL);
  1236 
  1120   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
  1237 /**
  1121 
  1238  * gst_app_sink_pull_buffer_list:
  1122   g_mutex_lock (appsink->priv->mutex);
  1239  * @appsink: a #GstAppSink
  1123 
  1240  *
  1124   while (TRUE) {
  1241  * This function blocks until a buffer list or EOS becomes available or the
  1125     GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
  1242  * appsink element is set to the READY/NULL state. 
  1126     if (!appsink->priv->started)
  1243  *
  1127       goto not_started;
  1244  * This function will only return buffer lists when the appsink is in the
  1128 
  1245  * PLAYING state. All rendered buffer lists will be put in a queue so that
  1129     if (!g_queue_is_empty (appsink->priv->queue))
  1246  * the application can pull buffer lists at its own rate. Note that when
  1130       break;
  1247  * the application does not pull buffer lists fast enough, the queued buffer
  1131 
  1248  * lists could consume a lot of memory, especially when dealing with raw
  1132     if (appsink->priv->is_eos)
  1249  * video frames.
  1133       goto eos;
  1250  *
  1134 
  1251  * If an EOS event was received before any buffer lists, this function returns
  1135     /* nothing to return, wait */
  1252  * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. 
  1136     GST_DEBUG_OBJECT (appsink, "waiting for a buffer");
  1253  *
  1137     g_cond_wait (appsink->priv->cond, appsink->priv->mutex);
  1254  * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
  1138   }
  1255  */
  1139   buf = g_queue_pop_head (appsink->priv->queue);
  1256 EXPORT_C GstBufferList *
  1140   GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buf);
  1257 gst_app_sink_pull_buffer_list (GstAppSink * appsink)
  1141   g_cond_signal (appsink->priv->cond);
  1258 {
  1142   g_mutex_unlock (appsink->priv->mutex);
  1259   GST_DEBUG_OBJECT (appsink, "pull a buffer list");
  1143 
  1260   return GST_BUFFER_LIST_CAST (gst_app_sink_pull_object (appsink));
  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   }
  1261 }
  1159 }
  1262 
  1160 
  1263 /**
  1161 /**
  1264  * gst_app_sink_set_callbacks:
  1162  * gst_app_sink_set_callbacks:
  1265  * @appsink: a #GstAppSink
  1163  * @appsink: a #GstAppSink
  1274  * If callbacks are installed, no signals will be emited for performance
  1172  * If callbacks are installed, no signals will be emited for performance
  1275  * reasons.
  1173  * reasons.
  1276  *
  1174  *
  1277  * Since: 0.10.23
  1175  * Since: 0.10.23
  1278  */
  1176  */
  1279 EXPORT_C void
  1177 void
  1280 gst_app_sink_set_callbacks (GstAppSink * appsink,
  1178 gst_app_sink_set_callbacks (GstAppSink * appsink,
  1281     GstAppSinkCallbacks * callbacks, gpointer user_data, GDestroyNotify notify)
  1179     GstAppSinkCallbacks * callbacks, gpointer user_data, GDestroyNotify notify)
  1282 {
  1180 {
  1283   GDestroyNotify old_notify;
  1181   GDestroyNotify old_notify;
  1284 
  1182