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