Use the new GstSample for snapshots
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 1 Dec 2011 15:48:49 +0000 (16:48 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 1 Dec 2011 15:53:11 +0000 (16:53 +0100)
Make appsink return a GstSample. Remove the pull_buffer_list method because it
is not very useful anymore.
Pass GstSample to the conversion function.
Update playbin2 and examples

13 files changed:
docs/libs/gst-plugins-base-libs-sections.txt
gst-libs/gst/app/gstappsink.c
gst-libs/gst/app/gstappsink.h
gst-libs/gst/audio/gstaudiobasesink.c
gst-libs/gst/video/convertframe.c
gst-libs/gst/video/video.h
gst/playback/gstplaybin2.c
gst/playback/gstplaysink.c
gst/playback/gstplaysink.h
tests/check/libs/video.c
tests/examples/app/appsink-src.c
tests/examples/app/appsrc_ex.c
tests/examples/seek/seek.c

index 7d8247648612fcf7fc4b4202b21791e56084ef9d..cd5c15c7869667e4ae4ef6351bfc1643612158dd 100644 (file)
@@ -60,8 +60,7 @@ gst_app_sink_get_max_buffers
 gst_app_sink_set_drop
 gst_app_sink_get_drop
 gst_app_sink_pull_preroll
-gst_app_sink_pull_buffer
-gst_app_sink_pull_buffer_list
+gst_app_sink_pull_sample
 GstAppSinkCallbacks
 gst_app_sink_set_callbacks
 <SUBSECTION Standard>
@@ -2103,9 +2102,9 @@ gst_video_calculate_display_ratio
 gst_video_format_to_fourcc
 gst_video_format_from_fourcc
 gst_video_parse_caps_palette
-GstVideoConvertFrameCallback
-gst_video_convert_frame
-gst_video_convert_frame_async
+GstVideoConvertSampleCallback
+gst_video_convert_sample
+gst_video_convert_sample_async
 gst_video_event_new_still_frame
 gst_video_event_parse_still_frame
 <SUBSECTION Standard>
index 3bfcd596a4c96d50f8b1c720150af2172ff746b9..5cb3d3903eb0bc93f87a24d05f3cd8dc8218a1b9 100644 (file)
@@ -19,9 +19,9 @@
  */
 /**
  * SECTION:gstappsink
- * @short_description: Easy way for applications to extract buffers from a
+ * @short_description: Easy way for applications to extract samples from a
  *     pipeline
- * @see_also: #GstBaseSink, appsrc
+ * @see_also: #GstSample, #GstBaseSink, appsrc
  *
  * Appsink is a sink plugin that supports many different methods for making
  * the application get a handle on the GStreamer data in a pipeline. Unlike
  * appsink can be used by linking to the gstappsink.h header file to access the
  * methods or by using the appsink action signals and properties.
  *
- * The normal way of retrieving buffers from appsink is by using the
- * gst_app_sink_pull_buffer() and gst_app_sink_pull_preroll() methods.
- * These methods block until a buffer becomes available in the sink or when the
+ * The normal way of retrieving samples from appsink is by using the
+ * gst_app_sink_pull_sample() and gst_app_sink_pull_preroll() methods.
+ * These methods block until a sample becomes available in the sink or when the
  * sink is shut down or reaches EOS.
  *
  * Appsink will internally use a queue to collect buffers from the streaming
- * thread. If the application is not pulling buffers fast enough, this queue
+ * thread. If the application is not pulling samples fast enough, this queue
  * will consume a lot of memory over time. The "max-buffers" property can be
  * used to limit the queue size. The "drop" property controls whether the
  * streaming thread blocks or if older buffers are dropped when the maximum
  * affect real-time performance and should be avoided.
  *
  * If a blocking behaviour is not desirable, setting the "emit-signals" property
- * to %TRUE will make appsink emit the "new-buffer" and "new-preroll" signals
- * when a buffer can be pulled without blocking.
+ * to %TRUE will make appsink emit the "new-sample" and "new-preroll" signals
+ * when a sample can be pulled without blocking.
  *
  * The "caps" property on appsink can be used to control the formats that
  * appsink can receive. This property can contain non-fixed caps, the format of
- * the pulled buffers can be obtained by getting the buffer caps.
+ * the pulled samples can be obtained by getting the sample caps.
  *
- * If one of the pull-preroll or pull-buffer methods return %NULL, the appsink
+ * If one of the pull-preroll or pull-sample methods return %NULL, the appsink
  * is stopped or in the EOS state. You can check for the EOS state with the
  * "eos" property or with the gst_app_sink_is_eos() method.
  *
 #include <gst/gst.h>
 #include <gst/base/gstbasesink.h>
 #include <gst/gstbuffer.h>
-#include <gst/gstbufferlist.h>
 
 #include <string.h>
 
+#include "gstapp-marshal.h"
 #include "gstappsink.h"
 
 struct _GstAppSinkPrivate
 {
   GstCaps *caps;
   gboolean emit_signals;
+  guint num_buffers;
   guint max_buffers;
   gboolean drop;
 
@@ -87,6 +88,9 @@ struct _GstAppSinkPrivate
   GMutex *mutex;
   GQueue *queue;
   GstBuffer *preroll;
+  GstCaps *preroll_caps;
+  GstCaps *last_caps;
+  GstSegment last_segment;
   gboolean flushing;
   gboolean unlock;
   gboolean started;
@@ -95,8 +99,6 @@ struct _GstAppSinkPrivate
   GstAppSinkCallbacks callbacks;
   gpointer user_data;
   GDestroyNotify notify;
-
-  gboolean buffer_lists_supported;
 };
 
 GST_DEBUG_CATEGORY_STATIC (app_sink_debug);
@@ -107,13 +109,11 @@ enum
   /* signals */
   SIGNAL_EOS,
   SIGNAL_NEW_PREROLL,
-  SIGNAL_NEW_BUFFER,
-  SIGNAL_NEW_BUFFER_LIST,
+  SIGNAL_NEW_SAMPLE,
 
   /* actions */
   SIGNAL_PULL_PREROLL,
-  SIGNAL_PULL_BUFFER,
-  SIGNAL_PULL_BUFFER_LIST,
+  SIGNAL_PULL_SAMPLE,
 
   LAST_SIGNAL
 };
@@ -158,14 +158,10 @@ static gboolean gst_app_sink_stop (GstBaseSink * psink);
 static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event);
 static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink,
     GstBuffer * buffer);
-static GstFlowReturn gst_app_sink_render_common (GstBaseSink * psink,
-    GstMiniObject * data, gboolean is_list);
 static GstFlowReturn gst_app_sink_render (GstBaseSink * psink,
     GstBuffer * buffer);
-static GstFlowReturn gst_app_sink_render_list (GstBaseSink * psink,
-    GstBufferList * list);
+static gboolean gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps);
 static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink, GstCaps * filter);
-static GstMiniObject *gst_app_sink_pull_object (GstAppSink * appsink);
 
 static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 };
 
@@ -174,40 +170,6 @@ G_DEFINE_TYPE_WITH_CODE (GstAppSink, gst_app_sink, GST_TYPE_BASE_SINK,
     G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
         gst_app_sink_uri_handler_init));
 
-/* Can't use glib-genmarshal for this, as it doesn't know how to handle
- * GstMiniObject-based types, which are a new fundamental type */
-static void
-gst_app_marshal_BUFFER__VOID (GClosure * closure,
-    GValue * return_value,
-    guint n_param_values,
-    const GValue * param_values,
-    gpointer invocation_hint, gpointer marshal_data)
-{
-  typedef GstBuffer *(*GMarshalFunc_BUFFER__VOID) (gpointer data1,
-      gpointer data2);
-  register GMarshalFunc_BUFFER__VOID callback;
-  register GCClosure *cc = (GCClosure *) closure;
-  register gpointer data1, data2;
-  GstBuffer *v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 1);
-
-  if (G_CCLOSURE_SWAP_DATA (closure)) {
-    data1 = closure->data;
-    data2 = g_value_peek_pointer (param_values + 0);
-  } else {
-    data1 = g_value_peek_pointer (param_values + 0);
-    data2 = closure->data;
-  }
-  callback =
-      (GMarshalFunc_BUFFER__VOID) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1, data2);
-
-  gst_value_take_buffer (return_value, v_return);
-}
-
 static void
 gst_app_sink_class_init (GstAppSinkClass * klass)
 {
@@ -265,12 +227,12 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
    * GstAppSink::new-preroll:
    * @appsink: the appsink element that emited the signal
    *
-   * Signal that a new preroll buffer is available.
+   * Signal that a new preroll sample is available.
    *
    * This signal is emited from the steaming thread and only when the
    * "emit-signals" property is %TRUE.
    *
-   * The new preroll buffer can be retrieved with the "pull-preroll" action
+   * The new preroll sample can be retrieved with the "pull-preroll" action
    * signal or gst_app_sink_pull_preroll() either from this signal callback
    * or from any other thread.
    *
@@ -282,126 +244,80 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
       G_STRUCT_OFFSET (GstAppSinkClass, new_preroll),
       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   /**
-   * GstAppSink::new-buffer:
-   * @appsink: the appsink element that emited the signal
-   *
-   * Signal that a new buffer is available.
-   *
-   * This signal is emited from the steaming thread and only when the
-   * "emit-signals" property is %TRUE.
-   *
-   * The new buffer can be retrieved with the "pull-buffer" action
-   * signal or gst_app_sink_pull_buffer() either from this signal callback
-   * or from any other thread.
-   *
-   * Note that this signal is only emited when the "emit-signals" property is
-   * set to %TRUE, which it is not by default for performance reasons.
-   */
-  gst_app_sink_signals[SIGNAL_NEW_BUFFER] =
-      g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstAppSinkClass, new_buffer),
-      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
-  /**
-   * GstAppSink::new-buffer-list:
+   * GstAppSink::new-sample:
    * @appsink: the appsink element that emited the signal
    *
-   * Signal that a new bufferlist is available.
+   * Signal that a new sample is available.
    *
    * This signal is emited from the steaming thread and only when the
    * "emit-signals" property is %TRUE.
    *
-   * The new buffer can be retrieved with the "pull-buffer-list" action
-   * signal or gst_app_sink_pull_buffer_list() either from this signal callback
+   * The new sample can be retrieved with the "pull-sample" action
+   * signal or gst_app_sink_pull_sample() either from this signal callback
    * or from any other thread.
    *
    * Note that this signal is only emited when the "emit-signals" property is
    * set to %TRUE, which it is not by default for performance reasons.
    */
-  gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST] =
-      g_signal_new ("new-buffer-list", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, new_buffer_list),
+  gst_app_sink_signals[SIGNAL_NEW_SAMPLE] =
+      g_signal_new ("new-sample", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstAppSinkClass, new_sample),
       NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
 
   /**
    * GstAppSink::pull-preroll:
    * @appsink: the appsink element to emit this signal on
    *
-   * Get the last preroll buffer in @appsink. This was the buffer that caused the
-   * appsink to preroll in the PAUSED state. This buffer can be pulled many times
+   * Get the last preroll sample in @appsink. This was the sample that caused the
+   * appsink to preroll in the PAUSED state. This sample can be pulled many times
    * and remains available to the application even after EOS.
    *
    * This function is typically used when dealing with a pipeline in the PAUSED
-   * state. Calling this function after doing a seek will give the buffer right
+   * state. Calling this function after doing a seek will give the sample right
    * after the seek position.
    *
-   * Note that the preroll buffer will also be returned as the first buffer
-   * when calling gst_app_sink_pull_buffer() or the "pull-buffer" action signal.
+   * Note that the preroll sample will also be returned as the first sample
+   * when calling gst_app_sink_pull_sample() or the "pull-sample" action signal.
    *
    * If an EOS event was received before any buffers, this function returns
    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
    *
-   * This function blocks until a preroll buffer or EOS is received or the appsink
+   * This function blocks until a preroll sample or EOS is received or the appsink
    * element is set to the READY/NULL state.
    *
-   * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
+   * Returns: a #GstSample or NULL when the appsink is stopped or EOS.
    */
   gst_app_sink_signals[SIGNAL_PULL_PREROLL] =
       g_signal_new ("pull-preroll", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
-          pull_preroll), NULL, NULL, gst_app_marshal_BUFFER__VOID,
-      GST_TYPE_BUFFER, 0, G_TYPE_NONE);
-  /**
-   * GstAppSink::pull-buffer:
-   * @appsink: the appsink element to emit this signal on
-   *
-   * This function blocks until a buffer or EOS becomes available or the appsink
-   * element is set to the READY/NULL state.
-   *
-   * This function will only return buffers when the appsink is in the PLAYING
-   * state. All rendered buffers will be put in a queue so that the application
-   * can pull buffers at its own rate.
-   *
-   * Note that when the application does not pull buffers fast enough, the
-   * queued buffers could consume a lot of memory, especially when dealing with
-   * raw video frames. It's possible to control the behaviour of the queue with
-   * the "drop" and "max-buffers" properties.
-   *
-   * If an EOS event was received before any buffers, this function returns
-   * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
-   *
-   * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
-   */
-  gst_app_sink_signals[SIGNAL_PULL_BUFFER] =
-      g_signal_new ("pull-buffer", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
-          pull_buffer), NULL, NULL, gst_app_marshal_BUFFER__VOID,
-      GST_TYPE_BUFFER, 0, G_TYPE_NONE);
+          pull_preroll), NULL, NULL, __gst_app_marshal_BOXED__VOID,
+      GST_TYPE_SAMPLE, 0, G_TYPE_NONE);
   /**
-   * GstAppSink::pull-buffer-list:
+   * GstAppSink::pull-sample:
    * @appsink: the appsink element to emit this signal on
    *
-   * This function blocks until a buffer list or EOS becomes available or the appsink
+   * This function blocks until a sample or EOS becomes available or the appsink
    * element is set to the READY/NULL state.
    *
-   * This function will only return bufferlists when the appsink is in the PLAYING
-   * state. All rendered bufferlists will be put in a queue so that the application
-   * can pull bufferlists at its own rate.
+   * This function will only return samples when the appsink is in the PLAYING
+   * state. All rendered samples will be put in a queue so that the application
+   * can pull samples at its own rate.
    *
-   * Note that when the application does not pull bufferlists fast enough, the
-   * queued bufferlists could consume a lot of memory, especially when dealing with
+   * Note that when the application does not pull samples fast enough, the
+   * queued samples could consume a lot of memory, especially when dealing with
    * raw video frames. It's possible to control the behaviour of the queue with
    * the "drop" and "max-buffers" properties.
    *
    * If an EOS event was received before any buffers, this function returns
    * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
    *
-   * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
+   * Returns: a #GstSample or NULL when the appsink is stopped or EOS.
    */
-  gst_app_sink_signals[SIGNAL_PULL_BUFFER_LIST] =
-      g_signal_new ("pull-buffer-list", G_TYPE_FROM_CLASS (klass),
+  gst_app_sink_signals[SIGNAL_PULL_SAMPLE] =
+      g_signal_new ("pull-sample", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass,
-          pull_buffer_list), NULL, NULL, gst_app_marshal_BUFFER__VOID,
-      GST_TYPE_BUFFER_LIST, 0, G_TYPE_NONE);
+          pull_sample), NULL, NULL, __gst_app_marshal_BOXED__VOID,
+      GST_TYPE_SAMPLE, 0, G_TYPE_NONE);
 
   gst_element_class_set_details_simple (element_class, "AppSink",
       "Generic/Sink", "Allow the application to get access to raw buffer",
@@ -417,12 +333,11 @@ gst_app_sink_class_init (GstAppSinkClass * klass)
   basesink_class->event = gst_app_sink_event;
   basesink_class->preroll = gst_app_sink_preroll;
   basesink_class->render = gst_app_sink_render;
-  basesink_class->render_list = gst_app_sink_render_list;
   basesink_class->get_caps = gst_app_sink_getcaps;
+  basesink_class->set_caps = gst_app_sink_setcaps;
 
   klass->pull_preroll = gst_app_sink_pull_preroll;
-  klass->pull_buffer = gst_app_sink_pull_buffer;
-  klass->pull_buffer_list = gst_app_sink_pull_buffer_list;
+  klass->pull_sample = gst_app_sink_pull_sample;
 
   g_type_class_add_private (klass, sizeof (GstAppSinkPrivate));
 }
@@ -466,12 +381,11 @@ gst_app_sink_dispose (GObject * obj)
   GST_OBJECT_UNLOCK (appsink);
 
   g_mutex_lock (priv->mutex);
-  if (priv->preroll) {
-    gst_buffer_unref (priv->preroll);
-    priv->preroll = NULL;
-  }
   while ((queue_obj = g_queue_pop_head (priv->queue)))
     gst_mini_object_unref (queue_obj);
+  gst_buffer_replace (&priv->preroll, NULL);
+  gst_caps_replace (&priv->preroll_caps, NULL);
+  gst_caps_replace (&priv->last_caps, NULL);
   g_mutex_unlock (priv->mutex);
 
   G_OBJECT_CLASS (parent_class)->dispose (obj);
@@ -591,24 +505,10 @@ gst_app_sink_flush_unlocked (GstAppSink * appsink)
   gst_buffer_replace (&priv->preroll, NULL);
   while ((obj = g_queue_pop_head (priv->queue)))
     gst_mini_object_unref (obj);
+  priv->num_buffers = 0;
   g_cond_signal (priv->cond);
 }
 
-#define NEW_BUFFER_LIST_SIGID \
-    gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST]
-
-static gboolean
-gst_app_sink_check_buffer_lists_support (GstAppSink * appsink)
-{
-  gboolean ret;
-
-  ret = (appsink->priv->callbacks.new_buffer_list != NULL) ||
-      g_signal_has_handler_pending (appsink, NEW_BUFFER_LIST_SIGID, 0, FALSE);
-
-  GST_INFO_OBJECT (appsink, "application supports buffer lists: %d", ret);
-  return ret;
-}
-
 static gboolean
 gst_app_sink_start (GstBaseSink * psink)
 {
@@ -619,8 +519,7 @@ gst_app_sink_start (GstBaseSink * psink)
   GST_DEBUG_OBJECT (appsink, "starting");
   priv->flushing = FALSE;
   priv->started = TRUE;
-  priv->buffer_lists_supported =
-      gst_app_sink_check_buffer_lists_support (appsink);
+  gst_segment_init (&priv->last_segment, GST_FORMAT_TIME);
   g_mutex_unlock (priv->mutex);
 
   return TRUE;
@@ -637,6 +536,23 @@ gst_app_sink_stop (GstBaseSink * psink)
   priv->flushing = TRUE;
   priv->started = FALSE;
   gst_app_sink_flush_unlocked (appsink);
+  gst_caps_replace (&priv->preroll_caps, NULL);
+  gst_caps_replace (&priv->last_caps, NULL);
+  g_mutex_unlock (priv->mutex);
+
+  return TRUE;
+}
+
+static gboolean
+gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps)
+{
+  GstAppSink *appsink = GST_APP_SINK_CAST (sink);
+  GstAppSinkPrivate *priv = appsink->priv;
+
+  g_mutex_lock (priv->mutex);
+  GST_DEBUG_OBJECT (appsink, "receiving CAPS");
+  g_queue_push_tail (priv->queue, gst_event_new_caps (caps));
+  gst_caps_replace (&priv->preroll_caps, caps);
   g_mutex_unlock (priv->mutex);
 
   return TRUE;
@@ -649,8 +565,13 @@ gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
   GstAppSinkPrivate *priv = appsink->priv;
 
   switch (event->type) {
+    case GST_EVENT_SEGMENT:
+      g_mutex_lock (priv->mutex);
+      GST_DEBUG_OBJECT (appsink, "receiving SEGMENT");
+      g_queue_push_tail (priv->queue, gst_event_ref (event));
+      g_mutex_unlock (priv->mutex);
+      break;
     case GST_EVENT_EOS:
-
       g_mutex_lock (priv->mutex);
       GST_DEBUG_OBJECT (appsink, "receiving EOS");
       priv->is_eos = TRUE;
@@ -715,9 +636,52 @@ flushing:
   }
 }
 
+static GstBuffer *
+dequeue_buffer (GstAppSink * appsink)
+{
+  GstAppSinkPrivate *priv = appsink->priv;
+  GstBuffer *buffer;
+
+  do {
+    GstMiniObject *obj;
+
+    obj = g_queue_pop_head (priv->queue);
+
+    if (GST_IS_BUFFER (obj)) {
+      buffer = GST_BUFFER_CAST (obj);
+      GST_DEBUG_OBJECT (appsink, "dequeued buffer %p", buffer);
+      priv->num_buffers--;
+      break;
+    } else if (GST_IS_EVENT (obj)) {
+      GstEvent *event = GST_EVENT_CAST (obj);
+
+      switch (GST_EVENT_TYPE (obj)) {
+        case GST_EVENT_CAPS:
+        {
+          GstCaps *caps;
+
+          gst_event_parse_caps (event, &caps);
+          GST_DEBUG_OBJECT (appsink, "activating caps %" GST_PTR_FORMAT, caps);
+          gst_caps_replace (priv->last_caps, caps);
+          break;
+        }
+        case GST_EVENT_SEGMENT:
+          gst_event_copy_segment (event, &priv->last_segment);
+          GST_DEBUG_OBJECT (appsink, "activated segment %" GST_SEGMENT_FORMAT,
+              &priv->last_segment);
+          break;
+        default:
+          break;
+      }
+      gst_mini_object_unref (obj);
+    }
+  } while (TRUE);
+
+  return buffer;
+}
+
 static GstFlowReturn
-gst_app_sink_render_common (GstBaseSink * psink, GstMiniObject * data,
-    gboolean is_list)
+gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
 {
   GstFlowReturn ret;
   GstAppSink *appsink = GST_APP_SINK_CAST (psink);
@@ -729,20 +693,21 @@ restart:
   if (priv->flushing)
     goto flushing;
 
-  GST_DEBUG_OBJECT (appsink, "pushing render buffer%s %p on queue (%d)",
-      is_list ? " list" : "", data, priv->queue->length);
+  GST_DEBUG_OBJECT (appsink, "pushing render buffer %p on queue (%d)",
+      buffer, priv->num_buffers);
 
-  while (priv->max_buffers > 0 && priv->queue->length >= priv->max_buffers) {
+  while (priv->max_buffers > 0 && priv->num_buffers >= priv->max_buffers) {
     if (priv->drop) {
-      GstMiniObject *obj;
+      GstBuffer *old;
 
-      /* we need to drop the oldest buffer/list and try again */
-      obj = g_queue_pop_head (priv->queue);
-      GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", obj);
-      gst_mini_object_unref (obj);
+      /* we need to drop the oldest buffer and try again */
+      if ((old = dequeue_buffer (appsink))) {
+        GST_DEBUG_OBJECT (appsink, "dropping old buffer %p", old);
+        gst_buffer_unref (old);
+      }
     } else {
       GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d",
-          priv->queue->length, priv->max_buffers);
+          priv->num_buffers, priv->max_buffers);
 
       if (priv->unlock) {
         /* we are asked to unlock, call the wait_preroll method */
@@ -761,22 +726,17 @@ restart:
     }
   }
   /* we need to ref the buffer when pushing it in the queue */
-  g_queue_push_tail (priv->queue, gst_mini_object_ref (data));
+  g_queue_push_tail (priv->queue, gst_buffer_ref (buffer));
+  priv->num_buffers++;
   g_cond_signal (priv->cond);
   emit = priv->emit_signals;
   g_mutex_unlock (priv->mutex);
 
-  if (is_list) {
-    if (priv->callbacks.new_buffer_list)
-      priv->callbacks.new_buffer_list (appsink, priv->user_data);
-    else if (emit)
-      g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST], 0);
-  } else {
-    if (priv->callbacks.new_buffer)
-      priv->callbacks.new_buffer (appsink, priv->user_data);
-    else if (emit)
-      g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0);
-  }
+  if (priv->callbacks.new_sample)
+    priv->callbacks.new_sample (appsink, priv->user_data);
+  else if (emit)
+    g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_SAMPLE], 0);
+
   return GST_FLOW_OK;
 
 flushing:
@@ -792,43 +752,6 @@ stopping:
   }
 }
 
-static GstFlowReturn
-gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
-{
-  return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (buffer),
-      FALSE);
-}
-
-static GstFlowReturn
-gst_app_sink_render_list (GstBaseSink * sink, GstBufferList * list)
-{
-  GstFlowReturn flow;
-  GstAppSink *appsink;
-  GstBuffer *buffer;
-  guint i, len;
-
-  appsink = GST_APP_SINK_CAST (sink);
-
-  if (appsink->priv->buffer_lists_supported)
-    return gst_app_sink_render_common (sink, GST_MINI_OBJECT_CAST (list), TRUE);
-
-  /* The application doesn't support buffer lists, extract individual buffers
-   * then and push them one-by-one */
-  GST_INFO_OBJECT (sink, "chaining each group in list as a merged buffer");
-
-  len = gst_buffer_list_length (list);
-
-  flow = GST_FLOW_OK;
-  for (i = 0; i < len; i++) {
-    buffer = gst_buffer_list_get (list, i);
-    flow = gst_app_sink_render (sink, buffer);
-    if (flow != GST_FLOW_OK)
-      break;
-  }
-
-  return flow;
-}
-
 static GstCaps *
 gst_app_sink_getcaps (GstBaseSink * psink, GstCaps * filter)
 {
@@ -849,55 +772,6 @@ gst_app_sink_getcaps (GstBaseSink * psink, GstCaps * filter)
   return caps;
 }
 
-static GstMiniObject *
-gst_app_sink_pull_object (GstAppSink * appsink)
-{
-  GstMiniObject *obj = NULL;
-  GstAppSinkPrivate *priv;
-
-  g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
-
-  priv = appsink->priv;
-
-  g_mutex_lock (priv->mutex);
-
-  while (TRUE) {
-    GST_DEBUG_OBJECT (appsink, "trying to grab a buffer/list");
-    if (!priv->started)
-      goto not_started;
-
-    if (!g_queue_is_empty (priv->queue))
-      break;
-
-    if (priv->is_eos)
-      goto eos;
-
-    /* nothing to return, wait */
-    GST_DEBUG_OBJECT (appsink, "waiting for a buffer/list");
-    g_cond_wait (priv->cond, priv->mutex);
-  }
-  obj = g_queue_pop_head (priv->queue);
-  GST_DEBUG_OBJECT (appsink, "we have a buffer/list %p", obj);
-  g_cond_signal (priv->cond);
-  g_mutex_unlock (priv->mutex);
-
-  return obj;
-
-  /* special conditions */
-eos:
-  {
-    GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
-    g_mutex_unlock (priv->mutex);
-    return NULL;
-  }
-not_started:
-  {
-    GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
-    g_mutex_unlock (priv->mutex);
-    return NULL;
-  }
-}
-
 /* external API */
 
 /**
@@ -968,13 +842,13 @@ gst_app_sink_get_caps (GstAppSink * appsink)
  * gst_app_sink_is_eos:
  * @appsink: a #GstAppSink
  *
- * Check if @appsink is EOS, which is when no more buffers can be pulled because
+ * Check if @appsink is EOS, which is when no more samples can be pulled because
  * an EOS event was received.
  *
  * This function also returns %TRUE when the appsink is not in the PAUSED or
  * PLAYING state.
  *
- * Returns: %TRUE if no more buffers can be pulled and the appsink is EOS.
+ * Returns: %TRUE if no more samples can be pulled and the appsink is EOS.
  *
  * Since: 0.10.22
  */
@@ -992,7 +866,7 @@ gst_app_sink_is_eos (GstAppSink * appsink)
   if (!priv->started)
     goto not_started;
 
-  if (priv->is_eos && g_queue_is_empty (priv->queue)) {
+  if (priv->is_eos && priv->num_buffers == 0) {
     GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty");
     ret = TRUE;
   } else {
@@ -1016,7 +890,7 @@ not_started:
  * @appsink: a #GstAppSink
  * @emit: the new state
  *
- * Make appsink emit the "new-preroll" and "new-buffer" signals. This option is
+ * Make appsink emit the "new-preroll" and "new-sample" signals. This option is
  * by default disabled because signal emission is expensive and unneeded when
  * the application prefers to operate in pull mode.
  *
@@ -1040,9 +914,9 @@ gst_app_sink_set_emit_signals (GstAppSink * appsink, gboolean emit)
  * gst_app_sink_get_emit_signals:
  * @appsink: a #GstAppSink
  *
- * Check if appsink will emit the "new-preroll" and "new-buffer" signals.
+ * Check if appsink will emit the "new-preroll" and "new-sample" signals.
  *
- * Returns: %TRUE if @appsink is emiting the "new-preroll" and "new-buffer"
+ * Returns: %TRUE if @appsink is emiting the "new-preroll" and "new-sample"
  * signals.
  *
  * Since: 0.10.22
@@ -1071,7 +945,7 @@ gst_app_sink_get_emit_signals (GstAppSink * appsink)
  *
  * Set the maximum amount of buffers that can be queued in @appsink. After this
  * amount of buffers are queued in appsink, any more buffers will block upstream
- * elements until a buffer is pulled from @appsink.
+ * elements until a sample is pulled from @appsink.
  *
  * Since: 0.10.22
  */
@@ -1181,31 +1055,31 @@ gst_app_sink_get_drop (GstAppSink * appsink)
  * gst_app_sink_pull_preroll:
  * @appsink: a #GstAppSink
  *
- * Get the last preroll buffer in @appsink. This was the buffer that caused the
- * appsink to preroll in the PAUSED state. This buffer can be pulled many times
+ * Get the last preroll sample in @appsink. This was the sample that caused the
+ * appsink to preroll in the PAUSED state. This sample can be pulled many times
  * and remains available to the application even after EOS.
  *
  * This function is typically used when dealing with a pipeline in the PAUSED
- * state. Calling this function after doing a seek will give the buffer right
+ * state. Calling this function after doing a seek will give the sample right
  * after the seek position.
  *
- * Note that the preroll buffer will also be returned as the first buffer
- * when calling gst_app_sink_pull_buffer().
+ * Note that the preroll sample will also be returned as the first sample
+ * when calling gst_app_sink_pull_sample().
  *
  * If an EOS event was received before any buffers, this function returns
  * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
  *
- * This function blocks until a preroll buffer or EOS is received or the appsink
+ * This function blocks until a preroll sample or EOS is received or the appsink
  * element is set to the READY/NULL state.
  *
  * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
  *
  * Since: 0.10.22
  */
-GstBuffer *
+GstSample *
 gst_app_sink_pull_preroll (GstAppSink * appsink)
 {
-  GstBuffer *buf = NULL;
+  GstSample *sample = NULL;
   GstAppSinkPrivate *priv;
 
   g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
@@ -1229,11 +1103,13 @@ gst_app_sink_pull_preroll (GstAppSink * appsink)
     GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer");
     g_cond_wait (priv->cond, priv->mutex);
   }
-  buf = gst_buffer_ref (priv->preroll);
-  GST_DEBUG_OBJECT (appsink, "we have the preroll buffer %p", buf);
+  sample =
+      gst_sample_new (priv->preroll, priv->preroll_caps, &priv->last_segment,
+      NULL);
+  GST_DEBUG_OBJECT (appsink, "we have the preroll sample %p", sample);
   g_mutex_unlock (priv->mutex);
 
-  return buf;
+  return sample;
 
   /* special conditions */
 eos:
@@ -1251,16 +1127,16 @@ not_started:
 }
 
 /**
- * gst_app_sink_pull_buffer:
+ * gst_app_sink_pull_sample:
  * @appsink: a #GstAppSink
  *
- * This function blocks until a buffer or EOS becomes available or the appsink
+ * This function blocks until a sample or EOS becomes available or the appsink
  * element is set to the READY/NULL state.
  *
- * This function will only return buffers when the appsink is in the PLAYING
+ * This function will only return samples when the appsink is in the PLAYING
  * state. All rendered buffers will be put in a queue so that the application
- * can pull buffers at its own rate. Note that when the application does not
- * pull buffers fast enough, the queued buffers could consume a lot of memory,
+ * can pull samples at its own rate. Note that when the application does not
+ * pull samples fast enough, the queued buffers could consume a lot of memory,
  * especially when dealing with raw video frames.
  *
  * If an EOS event was received before any buffers, this function returns
@@ -1271,37 +1147,57 @@ not_started:
  * Since: 0.10.22
  */
 
-GstBuffer *
-gst_app_sink_pull_buffer (GstAppSink * appsink)
+GstSample *
+gst_app_sink_pull_sample (GstAppSink * appsink)
 {
-  GST_DEBUG_OBJECT (appsink, "pull a buffer");
-  return GST_BUFFER_CAST (gst_app_sink_pull_object (appsink));
-}
+  GstSample *sample = NULL;
+  GstBuffer *buffer;
+  GstAppSinkPrivate *priv;
 
-/**
- * gst_app_sink_pull_buffer_list:
- * @appsink: a #GstAppSink
- *
- * This function blocks until a buffer list or EOS becomes available or the
- * appsink element is set to the READY/NULL state.
- *
- * This function will only return buffer lists when the appsink is in the
- * PLAYING state. All rendered buffer lists will be put in a queue so that
- * the application can pull buffer lists at its own rate. Note that when
- * the application does not pull buffer lists fast enough, the queued buffer
- * lists could consume a lot of memory, especially when dealing with raw
- * video frames.
- *
- * If an EOS event was received before any buffer lists, this function returns
- * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
- *
- * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS.
- */
-GstBufferList *
-gst_app_sink_pull_buffer_list (GstAppSink * appsink)
-{
-  GST_DEBUG_OBJECT (appsink, "pull a buffer list");
-  return GST_BUFFER_LIST_CAST (gst_app_sink_pull_object (appsink));
+  g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL);
+
+  priv = appsink->priv;
+
+  g_mutex_lock (priv->mutex);
+
+  while (TRUE) {
+    GST_DEBUG_OBJECT (appsink, "trying to grab a buffer");
+    if (!priv->started)
+      goto not_started;
+
+    if (priv->num_buffers == 0)
+      break;
+
+    if (priv->is_eos)
+      goto eos;
+
+    /* nothing to return, wait */
+    GST_DEBUG_OBJECT (appsink, "waiting for a buffer");
+    g_cond_wait (priv->cond, priv->mutex);
+  }
+  buffer = dequeue_buffer (appsink);
+  GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buffer);
+  sample = gst_sample_new (buffer, priv->last_caps, &priv->last_segment, NULL);
+  gst_buffer_unref (buffer);
+
+  g_cond_signal (priv->cond);
+  g_mutex_unlock (priv->mutex);
+
+  return sample;
+
+  /* special conditions */
+eos:
+  {
+    GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL");
+    g_mutex_unlock (priv->mutex);
+    return NULL;
+  }
+not_started:
+  {
+    GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL");
+    g_mutex_unlock (priv->mutex);
+    return NULL;
+  }
 }
 
 /**
@@ -1311,7 +1207,7 @@ gst_app_sink_pull_buffer_list (GstAppSink * appsink)
  * @user_data: a user_data argument for the callbacks
  * @notify: a destroy notify function
  *
- * Set callbacks which will be executed for each new preroll, new buffer and eos.
+ * Set callbacks which will be executed for each new preroll, new sample and eos.
  * This is an alternative to using the signals, it has lower overhead and is thus
  * less expensive, but also less flexible.
  *
@@ -1351,8 +1247,6 @@ gst_app_sink_set_callbacks (GstAppSink * appsink,
   priv->callbacks = *callbacks;
   priv->user_data = user_data;
   priv->notify = notify;
-  priv->buffer_lists_supported =
-      gst_app_sink_check_buffer_lists_support (appsink);
   GST_OBJECT_UNLOCK (appsink);
 }
 
index 4bca82b671f06966100cc95e6182d4ca78b6d641..5259dec6c5ed3e97710033c119477a0941934f9c 100644 (file)
@@ -47,20 +47,15 @@ typedef struct _GstAppSinkPrivate GstAppSinkPrivate;
  * GstAppSinkCallbacks:
  * @eos: Called when the end-of-stream has been reached. This callback
  *       is called from the steaming thread.
- * @new_preroll: Called when a new preroll buffer is available.
+ * @new_preroll: Called when a new preroll sample is available.
  *       This callback is called from the steaming thread.
- *       The new preroll buffer can be retrieved with
+ *       The new preroll sample can be retrieved with
  *       gst_app_sink_pull_preroll() either from this callback
  *       or from any other thread.
- * @new_buffer: Called when a new buffer is available.
+ * @new_sample: Called when a new sample is available.
  *       This callback is called from the steaming thread.
- *       The new buffer can be retrieved with
- *       gst_app_sink_pull_buffer() either from this callback
- *       or from any other thread.
- * @new_buffer_list: Called when a new bufferlist is available.
- *       This callback is called from the steaming thread.
- *       The new bufferlist can be retrieved with
- *       gst_app_sink_pull_buffer_list() either from this callback
+ *       The new sample can be retrieved with
+ *       gst_app_sink_pull_sample() either from this callback
  *       or from any other thread.
  *
  * A set of callbacks that can be installed on the appsink with
@@ -71,8 +66,7 @@ typedef struct _GstAppSinkPrivate GstAppSinkPrivate;
 typedef struct {
   void          (*eos)              (GstAppSink *sink, gpointer user_data);
   GstFlowReturn (*new_preroll)      (GstAppSink *sink, gpointer user_data);
-  GstFlowReturn (*new_buffer)       (GstAppSink *sink, gpointer user_data);
-  GstFlowReturn (*new_buffer_list)  (GstAppSink *sink, gpointer user_data);
+  GstFlowReturn (*new_sample)       (GstAppSink *sink, gpointer user_data);
 
   /*< private >*/
   gpointer     _gst_reserved[GST_PADDING];
@@ -96,13 +90,11 @@ struct _GstAppSinkClass
   /* signals */
   void        (*eos)              (GstAppSink *sink);
   void        (*new_preroll)      (GstAppSink *sink);
-  void        (*new_buffer)       (GstAppSink *sink);
-  void        (*new_buffer_list)  (GstAppSink *sink);
+  void        (*new_sample)       (GstAppSink *sink);
 
   /* actions */
-  GstBuffer     * (*pull_preroll)      (GstAppSink *sink);
-  GstBuffer     * (*pull_buffer)       (GstAppSink *sink);
-  GstBufferList * (*pull_buffer_list)  (GstAppSink *sink);
+  GstSample     * (*pull_preroll)      (GstAppSink *sink);
+  GstSample     * (*pull_sample)       (GstAppSink *sink);
 
   /*< private >*/
   gpointer     _gst_reserved[GST_PADDING];
@@ -124,9 +116,8 @@ guint           gst_app_sink_get_max_buffers  (GstAppSink *appsink);
 void            gst_app_sink_set_drop         (GstAppSink *appsink, gboolean drop);
 gboolean        gst_app_sink_get_drop         (GstAppSink *appsink);
 
-GstBuffer *     gst_app_sink_pull_preroll     (GstAppSink *appsink);
-GstBuffer *     gst_app_sink_pull_buffer      (GstAppSink *appsink);
-GstBufferList * gst_app_sink_pull_buffer_list (GstAppSink *appsink);
+GstSample *     gst_app_sink_pull_preroll     (GstAppSink *appsink);
+GstSample *     gst_app_sink_pull_sample      (GstAppSink *appsink);
 
 void            gst_app_sink_set_callbacks    (GstAppSink * appsink,
                                                GstAppSinkCallbacks *callbacks,
index d7c1090a4b4273ce5e01b921fa0c5dc3ec944ae7..19a1c653621838e6f9936c5593c8fef649a86a29 100644 (file)
@@ -318,7 +318,7 @@ gst_audio_base_sink_init (GstAudioBaseSink * audiobasesink)
   basesink->can_activate_push = TRUE;
   basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
 
-  gst_base_sink_set_last_buffer_enabled (basesink, FALSE);
+  gst_base_sink_set_last_sample_enabled (basesink, FALSE);
   if (DEFAULT_PROVIDE_CLOCK)
     GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
   else
index 663924822ca4f66429fc15e9280f0b234ef37dc8..73dcfb1fc85383624048b917ad0760497e7bb896 100644 (file)
@@ -144,13 +144,15 @@ build_convert_frame_pipeline (GstElement ** src_element,
     goto link_failed;
 
   GST_DEBUG ("linking csp->vscale");
-  if (!gst_element_link_pads (csp, "src", vscale, "sink"))
+  if (!gst_element_link_pads_full (csp, "src", vscale, "sink",
+          GST_PAD_LINK_CHECK_NOTHING))
     goto link_failed;
 
   if (caps_are_raw (to_caps)) {
     GST_DEBUG ("linking vscale->sink");
 
-    if (!gst_element_link_pads (vscale, "src", sink, "sink"))
+    if (!gst_element_link_pads_full (vscale, "src", sink, "sink",
+            GST_PAD_LINK_CHECK_NOTHING))
       goto link_failed;
   } else {
     encoder = get_encoder (to_caps, &error);
@@ -230,9 +232,8 @@ link_failed:
 }
 
 /**
- * gst_video_convert_frame:
- * @buf: a #GstBuffer
- * @from_caps: the #GstCaps to convert from
+ * gst_video_convert_sample:
+ * @sample: a #GstSample
  * @to_caps: the #GstCaps to convert to
  * @timeout: the maximum amount of time allowed for the processing.
  * @error: pointer to a #GError. Can be %NULL.
@@ -243,29 +244,36 @@ link_failed:
  *
  * The width, height and pixel-aspect-ratio can also be specified in the output caps.
  *
- * Returns: The converted #GstBuffer, or %NULL if an error happened (in which case @err
+ * Returns: The converted #GstSample, or %NULL if an error happened (in which case @err
  * will point to the #GError).
  *
  * Since: 0.10.31
  *
  */
-GstBuffer *
-gst_video_convert_frame (GstBuffer * buf, GstCaps * from_caps,
-    const GstCaps * to_caps, GstClockTime timeout, GError ** error)
+GstSample *
+gst_video_convert_sample (GstSample * sample, const GstCaps * to_caps,
+    GstClockTime timeout, GError ** error)
 {
   GstMessage *msg;
-  GstBuffer *result = NULL;
+  GstBuffer *buf;
+  GstSample *result = NULL;
   GError *err = NULL;
   GstBus *bus;
-  GstCaps *to_caps_copy = NULL;
+  GstCaps *from_caps, *to_caps_copy = NULL;
   GstFlowReturn ret;
   GstElement *pipeline, *src, *sink;
   guint i, n;
 
-  g_return_val_if_fail (buf != NULL, NULL);
+  g_return_val_if_fail (sample != NULL, NULL);
   g_return_val_if_fail (to_caps != NULL, NULL);
+
+  buf = gst_sample_get_buffer (sample);
+  g_return_val_if_fail (buf != NULL, NULL);
+
+  from_caps = gst_sample_get_caps (sample);
   g_return_val_if_fail (from_caps != NULL, NULL);
 
+
   to_caps_copy = gst_caps_new_empty ();
   n = gst_caps_get_size (to_caps);
   for (i = 0; i < n; i++) {
@@ -364,28 +372,30 @@ typedef struct
 {
   GMutex *mutex;
   GstElement *pipeline;
-  GstVideoConvertFrameCallback callback;
+  GstVideoConvertSampleCallback callback;
   gpointer user_data;
   GDestroyNotify destroy_notify;
   GMainContext *context;
-  GstBuffer *buffer;
+  GstSample *sample;
+  //GstBuffer *buffer;
   gulong timeout_id;
   gboolean finished;
-} GstVideoConvertFrameContext;
+} GstVideoConvertSampleContext;
 
 typedef struct
 {
-  GstVideoConvertFrameCallback callback;
-  GstBuffer *buffer;
+  GstVideoConvertSampleCallback callback;
+  GstSample *sample;
+  //GstBuffer *buffer;
   GError *error;
   gpointer user_data;
   GDestroyNotify destroy_notify;
 
-  GstVideoConvertFrameContext *context;
-} GstVideoConvertFrameCallbackContext;
+  GstVideoConvertSampleContext *context;
+} GstVideoConvertSampleCallbackContext;
 
 static void
-gst_video_convert_frame_context_free (GstVideoConvertFrameContext * ctx)
+gst_video_convert_frame_context_free (GstVideoConvertSampleContext * ctx)
 {
   /* Wait until all users of the mutex are done */
   g_mutex_lock (ctx->mutex);
@@ -393,29 +403,31 @@ gst_video_convert_frame_context_free (GstVideoConvertFrameContext * ctx)
   g_mutex_free (ctx->mutex);
   if (ctx->timeout_id)
     g_source_remove (ctx->timeout_id);
-  if (ctx->buffer)
-    gst_buffer_unref (ctx->buffer);
+  //if (ctx->buffer)
+  //  gst_buffer_unref (ctx->buffer);
+  if (ctx->sample)
+    gst_sample_unref (ctx->sample);
   g_main_context_unref (ctx->context);
 
   gst_element_set_state (ctx->pipeline, GST_STATE_NULL);
   gst_object_unref (ctx->pipeline);
 
-  g_slice_free (GstVideoConvertFrameContext, ctx);
+  g_slice_free (GstVideoConvertSampleContext, ctx);
 }
 
 static void
     gst_video_convert_frame_callback_context_free
-    (GstVideoConvertFrameCallbackContext * ctx)
+    (GstVideoConvertSampleCallbackContext * ctx)
 {
   if (ctx->context)
     gst_video_convert_frame_context_free (ctx->context);
-  g_slice_free (GstVideoConvertFrameCallbackContext, ctx);
+  g_slice_free (GstVideoConvertSampleCallbackContext, ctx);
 }
 
 static gboolean
-convert_frame_dispatch_callback (GstVideoConvertFrameCallbackContext * ctx)
+convert_frame_dispatch_callback (GstVideoConvertSampleCallbackContext * ctx)
 {
-  ctx->callback (ctx->buffer, ctx->error, ctx->user_data);
+  ctx->callback (ctx->sample, ctx->error, ctx->user_data);
 
   if (ctx->destroy_notify)
     ctx->destroy_notify (ctx->user_data);
@@ -424,21 +436,22 @@ convert_frame_dispatch_callback (GstVideoConvertFrameCallbackContext * ctx)
 }
 
 static void
-convert_frame_finish (GstVideoConvertFrameContext * context, GstBuffer * buffer,
-    GError * error)
+convert_frame_finish (GstVideoConvertSampleContext * context,
+    GstSample * sample, GError * error)
 {
   GSource *source;
-  GstVideoConvertFrameCallbackContext *ctx;
+  GstVideoConvertSampleCallbackContext *ctx;
 
   if (context->timeout_id)
     g_source_remove (context->timeout_id);
   context->timeout_id = 0;
 
-  ctx = g_slice_new (GstVideoConvertFrameCallbackContext);
+  ctx = g_slice_new (GstVideoConvertSampleCallbackContext);
   ctx->callback = context->callback;
   ctx->user_data = context->user_data;
   ctx->destroy_notify = context->destroy_notify;
-  ctx->buffer = buffer;
+  ctx->sample = sample;
+  //ctx->buffer = buffer;
   ctx->error = error;
   ctx->context = context;
 
@@ -453,7 +466,7 @@ convert_frame_finish (GstVideoConvertFrameContext * context, GstBuffer * buffer,
 }
 
 static gboolean
-convert_frame_timeout_callback (GstVideoConvertFrameContext * context)
+convert_frame_timeout_callback (GstVideoConvertSampleContext * context)
 {
   GError *error;
 
@@ -476,7 +489,7 @@ done:
 
 static gboolean
 convert_frame_bus_callback (GstBus * bus, GstMessage * message,
-    GstVideoConvertFrameContext * context)
+    GstVideoConvertSampleContext * context)
 {
   g_mutex_lock (context->mutex);
 
@@ -510,19 +523,21 @@ done:
 
 static void
 convert_frame_need_data_callback (GstElement * src, guint size,
-    GstVideoConvertFrameContext * context)
+    GstVideoConvertSampleContext * context)
 {
   GstFlowReturn ret = GST_FLOW_ERROR;
   GError *error;
+  GstBuffer *buffer;
 
   g_mutex_lock (context->mutex);
 
   if (context->finished)
     goto done;
 
-  g_signal_emit_by_name (src, "push-buffer", context->buffer, &ret);
-  gst_buffer_unref (context->buffer);
-  context->buffer = NULL;
+  buffer = gst_sample_get_buffer (context->sample);
+  g_signal_emit_by_name (src, "push-buffer", buffer, &ret);
+  gst_sample_unref (context->sample);
+  context->sample = NULL;
 
   if (ret != GST_FLOW_OK) {
     GST_ERROR ("Could not push video frame: %s", gst_flow_get_name (ret));
@@ -541,10 +556,10 @@ done:
 }
 
 static void
-convert_frame_new_buffer_callback (GstElement * sink,
-    GstVideoConvertFrameContext * context)
+convert_frame_new_preroll_callback (GstElement * sink,
+    GstVideoConvertSampleContext * context)
 {
-  GstBuffer *buf = NULL;
+  GstSample *sample = NULL;
   GError *error = NULL;
 
   g_mutex_lock (context->mutex);
@@ -552,14 +567,13 @@ convert_frame_new_buffer_callback (GstElement * sink,
   if (context->finished)
     goto done;
 
-  g_signal_emit_by_name (sink, "pull-preroll", &buf);
+  g_signal_emit_by_name (sink, "pull-preroll", &sample);
 
-  if (!buf) {
+  if (!sample) {
     error = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
-        "Could not get converted video frame");
+        "Could not get converted video sample");
   }
-
-  convert_frame_finish (context, buf, error);
+  convert_frame_finish (context, sample, error);
 
   g_signal_handlers_disconnect_by_func (sink, convert_frame_need_data_callback,
       context);
@@ -569,12 +583,11 @@ done:
 }
 
 /**
- * gst_video_convert_frame_async:
- * @buf: a #GstBuffer
- * @from_caps: the #GstCaps to convert from
+ * gst_video_convert_sample_async:
+ * @sample: a #GstSample
  * @to_caps: the #GstCaps to convert to
  * @timeout: the maximum amount of time allowed for the processing.
- * @callback: %GstVideoConvertFrameCallback that will be called after conversion.
+ * @callback: %GstVideoConvertSampleCallback that will be called after conversion.
  * @user_data: extra data that will be passed to the @callback
  * @destroy_notify: %GDestroyNotify to be called after @user_data is not needed anymore
  *
@@ -596,22 +609,28 @@ done:
  *
  */
 void
-gst_video_convert_frame_async (GstBuffer * buf, GstCaps * from_caps,
+gst_video_convert_sample_async (GstSample * sample,
     const GstCaps * to_caps, GstClockTime timeout,
-    GstVideoConvertFrameCallback callback, gpointer user_data,
+    GstVideoConvertSampleCallback callback, gpointer user_data,
     GDestroyNotify destroy_notify)
 {
   GMainContext *context = NULL;
   GError *error = NULL;
   GstBus *bus;
-  GstCaps *to_caps_copy = NULL;
+  GstBuffer *buf;
+  GstCaps *from_caps, *to_caps_copy = NULL;
   GstElement *pipeline, *src, *sink;
   guint i, n;
   GSource *source;
-  GstVideoConvertFrameContext *ctx;
+  GstVideoConvertSampleContext *ctx;
 
+  g_return_if_fail (sample != NULL);
+  buf = gst_sample_get_buffer (sample);
   g_return_if_fail (buf != NULL);
+
   g_return_if_fail (to_caps != NULL);
+
+  from_caps = gst_sample_get_caps (sample);
   g_return_if_fail (from_caps != NULL);
   g_return_if_fail (callback != NULL);
 
@@ -638,9 +657,10 @@ gst_video_convert_frame_async (GstBuffer * buf, GstCaps * from_caps,
 
   bus = gst_element_get_bus (pipeline);
 
-  ctx = g_slice_new0 (GstVideoConvertFrameContext);
+  ctx = g_slice_new0 (GstVideoConvertSampleContext);
   ctx->mutex = g_mutex_new ();
-  ctx->buffer = gst_buffer_ref (buf);
+  //ctx->buffer = gst_buffer_ref (buf);
+  ctx->sample = gst_sample_ref (sample);
   ctx->callback = callback;
   ctx->user_data = user_data;
   ctx->destroy_notify = destroy_notify;
@@ -659,7 +679,7 @@ gst_video_convert_frame_async (GstBuffer * buf, GstCaps * from_caps,
   g_signal_connect (src, "need-data",
       G_CALLBACK (convert_frame_need_data_callback), ctx);
   g_signal_connect (sink, "new-preroll",
-      G_CALLBACK (convert_frame_new_buffer_callback), ctx);
+      G_CALLBACK (convert_frame_new_preroll_callback), ctx);
 
   source = gst_bus_create_watch (bus);
   g_source_set_callback (source, (GSourceFunc) convert_frame_bus_callback,
@@ -676,16 +696,16 @@ gst_video_convert_frame_async (GstBuffer * buf, GstCaps * from_caps,
   /* ERRORS */
 no_pipeline:
   {
-    GstVideoConvertFrameCallbackContext *ctx;
+    GstVideoConvertSampleCallbackContext *ctx;
     GSource *source;
 
     gst_caps_unref (to_caps_copy);
 
-    ctx = g_slice_new0 (GstVideoConvertFrameCallbackContext);
+    ctx = g_slice_new0 (GstVideoConvertSampleCallbackContext);
     ctx->callback = callback;
     ctx->user_data = user_data;
     ctx->destroy_notify = destroy_notify;
-    ctx->buffer = NULL;
+    ctx->sample = NULL;
     ctx->error = error;
 
     source = g_timeout_source_new (0);
index 42a2024e4a459ecaa8893e9faeaf5d6937742dc6..57dff7ac67962341a2bdd4e26cef337480f96ebf 100644 (file)
@@ -705,20 +705,18 @@ GstEvent *     gst_video_event_new_still_frame   (gboolean in_still);
 gboolean       gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still);
 
 
-/* convert/encode video frame from one format to another */
+/* convert/encode video sample from one format to another */
 
-typedef void (*GstVideoConvertFrameCallback) (GstBuffer * buf, GError *error, gpointer user_data);
+typedef void (*GstVideoConvertSampleCallback) (GstSample * sample, GError *error, gpointer user_data);
 
-void           gst_video_convert_frame_async (GstBuffer                    * buf,
-                                              GstCaps                      * from_caps,
+void          gst_video_convert_sample_async (GstSample                    * sample,
                                               const GstCaps                * to_caps,
                                               GstClockTime                   timeout,
-                                              GstVideoConvertFrameCallback   callback,
+                                              GstVideoConvertSampleCallback  callback,
                                               gpointer                       user_data,
                                               GDestroyNotify                 destroy_notify);
 
-GstBuffer *    gst_video_convert_frame       (GstBuffer     * buf,
-                                              GstCaps       * from_caps,
+GstSample *   gst_video_convert_sample       (GstSample     * sample,
                                               const GstCaps * to_caps,
                                               GstClockTime    timeout,
                                               GError       ** error);
index b99c28c4659ca7789979d981fb45acc1f931d9cd..f29ce8eebe7115d5129a70087c35ab1dfcbc72eb 100644 (file)
@@ -44,7 +44,7 @@
  * meta info (tag) extraction
  * </listitem>
  * <listitem>
- * easy access to the last video frame
+ * easy access to the last video sample
  * </listitem>
  * <listitem>
  * buffering when playing streams over a network
@@ -436,8 +436,8 @@ struct _GstPlayBinClass
   GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
   GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream);
 
-  /* get the last video frame and convert it to the given caps */
-  GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps);
+  /* get the last video sample and convert it to the given caps */
+  GstSample *(*convert_sample) (GstPlayBin * playbin, GstCaps * caps);
 
   /* get audio/video/text pad for a stream */
   GstPad *(*get_video_pad) (GstPlayBin * playbin, gint stream);
@@ -491,7 +491,7 @@ enum
   PROP_TEXT_SINK,
   PROP_VOLUME,
   PROP_MUTE,
-  PROP_FRAME,
+  PROP_SAMPLE,
   PROP_FONT_DESC,
   PROP_CONNECTION_SPEED,
   PROP_BUFFER_SIZE,
@@ -505,7 +505,7 @@ enum
 enum
 {
   SIGNAL_ABOUT_TO_FINISH,
-  SIGNAL_CONVERT_FRAME,
+  SIGNAL_CONVERT_SAMPLE,
   SIGNAL_VIDEO_CHANGED,
   SIGNAL_AUDIO_CHANGED,
   SIGNAL_TEXT_CHANGED,
@@ -544,7 +544,7 @@ static GstTagList *gst_play_bin_get_audio_tags (GstPlayBin * playbin,
 static GstTagList *gst_play_bin_get_text_tags (GstPlayBin * playbin,
     gint stream);
 
-static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin,
+static GstSample *gst_play_bin_convert_sample (GstPlayBin * playbin,
     GstCaps * caps);
 
 static GstPad *gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream);
@@ -756,16 +756,17 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstPlayBin:frame:
+   * GstPlayBin:sample:
    * @playbin: a #GstPlayBin
    *
-   * Get the currently rendered or prerolled frame in the video sink.
-   * The #GstCaps on the buffer will describe the format of the buffer.
+   * Get the currently rendered or prerolled sample in the video sink.
+   * The #GstCaps in the sample will describe the format of the buffer.
    */
-  g_object_class_install_property (gobject_klass, PROP_FRAME,
-      g_param_spec_boxed ("frame", "Frame",
-          "The last frame (NULL = no video available)",
-          GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_klass, PROP_SAMPLE,
+      g_param_spec_boxed ("sample", "Sample",
+          "The last sample (NULL = no video available)",
+          GST_TYPE_SAMPLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
       g_param_spec_string ("subtitle-font-desc",
           "Subtitle font description",
@@ -1019,7 +1020,7 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
       G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   /**
-   * GstPlayBin::convert-frame
+   * GstPlayBin::convert-sample
    * @playbin: a #GstPlayBin
    * @caps: the target format of the frame
    *
@@ -1033,11 +1034,11 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
    * %NULL is returned when no current buffer can be retrieved or when the
    * conversion failed.
    */
-  gst_play_bin_signals[SIGNAL_CONVERT_FRAME] =
-      g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
+  gst_play_bin_signals[SIGNAL_CONVERT_SAMPLE] =
+      g_signal_new ("convert-sample", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-      G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL,
-      gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
+      G_STRUCT_OFFSET (GstPlayBinClass, convert_sample), NULL, NULL,
+      gst_play_marshal_SAMPLE__BOXED, GST_TYPE_SAMPLE, 1, GST_TYPE_CAPS);
 
   /**
    * GstPlayBin::get-video-pad
@@ -1095,7 +1096,7 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
   klass->get_audio_tags = gst_play_bin_get_audio_tags;
   klass->get_text_tags = gst_play_bin_get_text_tags;
 
-  klass->convert_frame = gst_play_bin_convert_frame;
+  klass->convert_sample = gst_play_bin_convert_sample;
 
   klass->get_video_pad = gst_play_bin_get_video_pad;
   klass->get_audio_pad = gst_play_bin_get_audio_pad;
@@ -1524,10 +1525,10 @@ gst_play_bin_get_text_tags (GstPlayBin * playbin, gint stream)
   return result;
 }
 
-static GstBuffer *
-gst_play_bin_convert_frame (GstPlayBin * playbin, GstCaps * caps)
+static GstSample *
+gst_play_bin_convert_sample (GstPlayBin * playbin, GstCaps * caps)
 {
-  return gst_play_sink_convert_frame (playbin->playsink, caps);
+  return gst_play_sink_convert_sample (playbin->playsink, caps);
 }
 
 /* Returns current stream number, or -1 if none has been selected yet */
@@ -2104,9 +2105,9 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_MUTE:
       g_value_set_boolean (value, gst_play_sink_get_mute (playbin->playsink));
       break;
-    case PROP_FRAME:
-      gst_value_take_buffer (value,
-          gst_play_sink_get_last_frame (playbin->playsink));
+    case PROP_SAMPLE:
+      gst_value_take_sample (value,
+          gst_play_sink_get_last_sample (playbin->playsink));
       break;
     case PROP_FONT_DESC:
       g_value_take_string (value,
index 0259204e0455e7cce4e86e9c7b996f94f29e17f6..9f533535346940cd81ba4e27e4dd21dedd6dcd7e 100644 (file)
@@ -210,7 +210,7 @@ struct _GstPlaySinkClass
 
     gboolean (*reconfigure) (GstPlaySink * playsink);
 
-  GstBuffer *(*convert_frame) (GstPlaySink * playsink, GstCaps * caps);
+  GstSample *(*convert_sample) (GstPlaySink * playsink, GstCaps * caps);
 };
 
 
@@ -252,7 +252,7 @@ enum
   PROP_FONT_DESC,
   PROP_SUBTITLE_ENCODING,
   PROP_VIS_PLUGIN,
-  PROP_FRAME,
+  PROP_SAMPLE,
   PROP_AV_OFFSET,
   PROP_VIDEO_SINK,
   PROP_AUDIO_SINK,
@@ -292,18 +292,18 @@ static void notify_mute_cb (GObject * object, GParamSpec * pspec,
 static void update_av_offset (GstPlaySink * playsink);
 
 void
-gst_play_marshal_BUFFER__BOXED (GClosure * closure,
+gst_play_marshal_SAMPLE__BOXED (GClosure * closure,
     GValue * return_value G_GNUC_UNUSED,
     guint n_param_values,
     const GValue * param_values,
     gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
 {
-  typedef GstBuffer *(*GMarshalFunc_OBJECT__BOXED) (gpointer data1,
+  typedef GstSample *(*GMarshalFunc_OBJECT__BOXED) (gpointer data1,
       gpointer arg_1, gpointer data2);
   register GMarshalFunc_OBJECT__BOXED callback;
   register GCClosure *cc = (GCClosure *) closure;
   register gpointer data1, data2;
-  GstBuffer *v_return;
+  GstSample *v_return;
   g_return_if_fail (return_value != NULL);
   g_return_if_fail (n_param_values == 2);
 
@@ -319,7 +319,7 @@ gst_play_marshal_BUFFER__BOXED (GClosure * closure,
 
   v_return = callback (data1, g_value_get_boxed (param_values + 1), data2);
 
-  gst_value_take_buffer (return_value, v_return);
+  gst_value_take_sample (return_value, v_return);
 }
 
 /* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
@@ -386,17 +386,15 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
           "the visualization element to use (NULL = default)",
           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
-   * GstPlaySink:frame:
+   * GstPlaySink:sample:
    *
-   * Get the currently rendered or prerolled frame in the video sink.
-   * The #GstCaps on the buffer will describe the format of the buffer.
-   *
-   * Since: 0.10.30
+   * Get the currently rendered or prerolled sample in the video sink.
+   * The #GstCaps in the sample will describe the format of the buffer.
    */
-  g_object_class_install_property (gobject_klass, PROP_FRAME,
-      g_param_spec_boxed ("frame", "Frame",
-          "The last frame (NULL = no video available)",
-          GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_klass, PROP_SAMPLE,
+      g_param_spec_boxed ("sample", "Sample",
+          "The last sample (NULL = no video available)",
+          GST_TYPE_SAMPLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   /**
    * GstPlaySink:av-offset:
    *
@@ -455,26 +453,24 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
           reconfigure), NULL, NULL, gst_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN,
       0, G_TYPE_NONE);
   /**
-   * GstPlaySink::convert-frame
+   * GstPlaySink::convert-sample
    * @playsink: a #GstPlaySink
-   * @caps: the target format of the frame
+   * @caps: the target format of the sample
    *
-   * Action signal to retrieve the currently playing video frame in the format
+   * Action signal to retrieve the currently playing video sample in the format
    * specified by @caps.
    * If @caps is %NULL, no conversion will be performed and this function is
-   * equivalent to the #GstPlaySink::frame property.
+   * equivalent to the #GstPlaySink::sample property.
    *
-   * Returns: a #GstBuffer of the current video frame converted to #caps.
-   * The caps on the buffer will describe the final layout of the buffer data.
-   * %NULL is returned when no current buffer can be retrieved or when the
+   * Returns: a #GstSample of the current video sample converted to #caps.
+   * The caps in the sample will describe the final layout of the buffer data.
+   * %NULL is returned when no current sample can be retrieved or when the
    * conversion failed.
-   *
-   * Since: 0.10.30
    */
-  g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
+  g_signal_new ("convert-sample", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-      G_STRUCT_OFFSET (GstPlaySinkClass, convert_frame), NULL, NULL,
-      gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
+      G_STRUCT_OFFSET (GstPlaySinkClass, convert_sample), NULL, NULL,
+      gst_play_marshal_SAMPLE__BOXED, GST_TYPE_SAMPLE, 1, GST_TYPE_CAPS);
 
   gst_element_class_add_pad_template (gstelement_klass,
       gst_static_pad_template_get (&audiorawtemplate));
@@ -503,7 +499,7 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
       GST_DEBUG_FUNCPTR (gst_play_sink_handle_message);
 
   klass->reconfigure = GST_DEBUG_FUNCPTR (gst_play_sink_reconfigure);
-  klass->convert_frame = GST_DEBUG_FUNCPTR (gst_play_sink_convert_frame);
+  klass->convert_sample = GST_DEBUG_FUNCPTR (gst_play_sink_convert_sample);
 }
 
 static void
@@ -2797,24 +2793,24 @@ gst_play_sink_get_av_offset (GstPlaySink * playsink)
 }
 
 /**
- * gst_play_sink_get_last_frame:
+ * gst_play_sink_get_last_sample:
  * @playsink: a #GstPlaySink
  *
- * Get the last displayed frame from @playsink. This frame is in the native
- * format of the sink element, the caps on the result buffer contain the format
+ * Get the last displayed sample from @playsink. This sample is in the native
+ * format of the sink element, the caps in the result sample contain the format
  * of the frame data.
  *
- * Returns: a #GstBuffer with the frame data or %NULL when no video frame is
+ * Returns: a #GstSample with the frame data or %NULL when no video frame is
  * available.
  */
-GstBuffer *
-gst_play_sink_get_last_frame (GstPlaySink * playsink)
+GstSample *
+gst_play_sink_get_last_sample (GstPlaySink * playsink)
 {
-  GstBuffer *result = NULL;
+  GstSample *result = NULL;
   GstPlayVideoChain *chain;
 
   GST_PLAY_SINK_LOCK (playsink);
-  GST_DEBUG_OBJECT (playsink, "taking last frame");
+  GST_DEBUG_OBJECT (playsink, "taking last sample");
   /* get the video chain if we can */
   if ((chain = (GstPlayVideoChain *) playsink->videochain)) {
     GST_DEBUG_OBJECT (playsink, "found video chain");
@@ -2827,9 +2823,9 @@ gst_play_sink_get_last_frame (GstPlaySink * playsink)
       /* find and get the last-buffer property now */
       if ((elem =
               gst_play_sink_find_property (playsink, chain->sink,
-                  "last-buffer", GST_TYPE_BUFFER))) {
-        GST_DEBUG_OBJECT (playsink, "getting last-buffer property");
-        g_object_get (elem, "last-buffer", &result, NULL);
+                  "last-sample", GST_TYPE_SAMPLE))) {
+        GST_DEBUG_OBJECT (playsink, "getting last-sample property");
+        g_object_get (elem, "last-sample", &result, NULL);
         gst_object_unref (elem);
       }
     }
@@ -2840,7 +2836,7 @@ gst_play_sink_get_last_frame (GstPlaySink * playsink)
 }
 
 /**
- * gst_play_sink_convert_frame:
+ * gst_play_sink_convert_sample:
  * @playsink: a #GstPlaySink
  * @caps: a #GstCaps
  *
@@ -2852,28 +2848,36 @@ gst_play_sink_get_last_frame (GstPlaySink * playsink)
  * Returns: a #GstBuffer with the frame data or %NULL when no video frame is
  * available or when the conversion failed.
  */
-GstBuffer *
-gst_play_sink_convert_frame (GstPlaySink * playsink, GstCaps * caps)
+GstSample *
+gst_play_sink_convert_sample (GstPlaySink * playsink, GstCaps * caps)
 {
-  GstBuffer *result;
+  GstSample *result;
+  GError *err = NULL;
 
-  result = gst_play_sink_get_last_frame (playsink);
+  result = gst_play_sink_get_last_sample (playsink);
   if (result != NULL && caps != NULL) {
-    GstBuffer *temp;
-    GError *err = NULL;
-
-    /* FIXME, need to get the input buffer caps */
-    temp = gst_video_convert_frame (result, NULL, caps, 25 * GST_SECOND, &err);
-    gst_buffer_unref (result);
-    if (temp == NULL && err) {
-      /* I'm really uncertain whether we should make playsink post an error
-       * on the bus or not. It's not like it's a critical issue regarding
-       * playsink behaviour. */
-      GST_ERROR ("Error converting frame: %s", err->message);
-    }
+    GstSample *temp;
+
+    temp = gst_video_convert_sample (result, caps, 25 * GST_SECOND, &err);
+    if (temp == NULL && err)
+      goto error;
+
+    gst_sample_unref (result);
     result = temp;
   }
   return result;
+
+  /* ERRORS */
+error:
+  {
+    /* I'm really uncertain whether we should make playsink post an error
+     * on the bus or not. It's not like it's a critical issue regarding
+     * playsink behaviour. */
+    GST_ERROR ("Error converting frame: %s", err->message);
+    gst_sample_unref (result);
+    g_error_free (err);
+    return NULL;
+  }
 }
 
 static gboolean
@@ -3700,8 +3704,8 @@ gst_play_sink_get_property (GObject * object, guint prop_id,
     case PROP_VIS_PLUGIN:
       g_value_take_object (value, gst_play_sink_get_vis_plugin (playsink));
       break;
-    case PROP_FRAME:
-      gst_value_take_buffer (value, gst_play_sink_get_last_frame (playsink));
+    case PROP_SAMPLE:
+      gst_value_take_sample (value, gst_play_sink_get_last_sample (playsink));
       break;
     case PROP_AV_OFFSET:
       g_value_set_int64 (value, gst_play_sink_get_av_offset (playsink));
index 6759ea438e0dd9ee3272e138b8af400b7eea54f7..51fe14b743794016c692812ee9c6b293ced63a24 100644 (file)
@@ -94,15 +94,15 @@ gchar *          gst_play_sink_get_subtitle_encoding  (GstPlaySink *playsink);
 void             gst_play_sink_set_av_offset  (GstPlaySink *playsink, gint64 av_offset);
 gint64           gst_play_sink_get_av_offset  (GstPlaySink *playsink);
 
-GstBuffer *      gst_play_sink_get_last_frame (GstPlaySink * playsink);
-GstBuffer *      gst_play_sink_convert_frame  (GstPlaySink * playsink, GstCaps * caps);
+GstSample *      gst_play_sink_get_last_sample (GstPlaySink * playsink);
+GstSample *      gst_play_sink_convert_sample  (GstPlaySink * playsink, GstCaps * caps);
 
 gboolean         gst_play_sink_reconfigure    (GstPlaySink * playsink);
 
 gboolean         gst_play_sink_plugin_init    (GstPlugin * plugin);
 
 void
-gst_play_marshal_BUFFER__BOXED (GClosure * closure,
+gst_play_marshal_SAMPLE__BOXED (GClosure * closure,
     GValue * return_value G_GNUC_UNUSED,
     guint n_param_values,
     const GValue * param_values,
index 67198239c58a1e5ae1853f4aaafd589a7128ab2c..1d826f064a6f1c3ecbc3c5d0e40827e89a1c397a 100644 (file)
@@ -667,7 +667,8 @@ GST_START_TEST (test_convert_frame)
 {
   GstVideoInfo vinfo;
   GstCaps *from_caps, *to_caps;
-  GstBuffer *from_buffer, *to_buffer;
+  GstBuffer *from_buffer;
+  GstSample *from_sample, *to_sample;
   GError *error = NULL;
   gint i;
   guint8 *data;
@@ -693,14 +694,16 @@ GST_START_TEST (test_convert_frame)
   vinfo.par_d = 1;
   from_caps = gst_video_info_to_caps (&vinfo);
 
+  from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
+
   to_caps =
       gst_caps_from_string
       ("something/that, does=(string)not, exist=(boolean)FALSE");
 
-  to_buffer =
-      gst_video_convert_frame (from_buffer, from_caps, to_caps,
+  to_sample =
+      gst_video_convert_sample (from_sample, to_caps,
       GST_CLOCK_TIME_NONE, &error);
-  fail_if (to_buffer != NULL);
+  fail_if (to_sample != NULL);
   fail_unless (error != NULL);
   g_error_free (error);
   error = NULL;
@@ -713,15 +716,16 @@ GST_START_TEST (test_convert_frame)
   vinfo.par_d = 2;
   to_caps = gst_video_info_to_caps (&vinfo);
 
-  to_buffer =
-      gst_video_convert_frame (from_buffer, from_caps, to_caps,
+  to_sample =
+      gst_video_convert_sample (from_sample, to_caps,
       GST_CLOCK_TIME_NONE, &error);
-  fail_unless (to_buffer != NULL);
+  fail_unless (to_sample != NULL);
   fail_unless (error == NULL);
 
   gst_buffer_unref (from_buffer);
   gst_caps_unref (from_caps);
-  gst_buffer_unref (to_buffer);
+  gst_sample_unref (from_sample);
+  gst_sample_unref (to_sample);
   gst_caps_unref (to_caps);
 }
 
@@ -730,15 +734,15 @@ GST_END_TEST;
 typedef struct
 {
   GMainLoop *loop;
-  GstBuffer *buffer;
+  GstSample *sample;
   GError *error;
 } ConvertFrameContext;
 
 static void
-convert_frame_async_callback (GstBuffer * buf, GError * err,
+convert_sample_async_callback (GstSample * sample, GError * err,
     ConvertFrameContext * cf_data)
 {
-  cf_data->buffer = buf;
+  cf_data->sample = sample;
   cf_data->error = err;
 
   g_main_loop_quit (cf_data->loop);
@@ -749,6 +753,7 @@ GST_START_TEST (test_convert_frame_async)
   GstVideoInfo vinfo;
   GstCaps *from_caps, *to_caps;
   GstBuffer *from_buffer;
+  GstSample *from_sample;
   gint i;
   guint8 *data;
   GMainLoop *loop;
@@ -781,14 +786,18 @@ GST_START_TEST (test_convert_frame_async)
 
   loop = cf_data.loop = g_main_loop_new (NULL, FALSE);
 
-  gst_video_convert_frame_async (from_buffer, from_caps, to_caps,
+  from_sample = gst_sample_new (from_buffer, from_caps, NULL, NULL);
+  gst_buffer_unref (from_buffer);
+  gst_caps_unref (from_caps);
+
+  gst_video_convert_sample_async (from_sample, to_caps,
       GST_CLOCK_TIME_NONE,
-      (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data,
+      (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
       NULL);
 
   g_main_loop_run (loop);
 
-  fail_if (cf_data.buffer != NULL);
+  fail_if (cf_data.sample != NULL);
   fail_unless (cf_data.error != NULL);
   g_error_free (cf_data.error);
   cf_data.error = NULL;
@@ -801,17 +810,15 @@ GST_START_TEST (test_convert_frame_async)
   vinfo.fps_n = 25;
   vinfo.fps_d = 1;
   to_caps = gst_video_info_to_caps (&vinfo);
-  gst_video_convert_frame_async (from_buffer, from_caps, to_caps,
+  gst_video_convert_sample_async (from_sample, to_caps,
       GST_CLOCK_TIME_NONE,
-      (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data,
+      (GstVideoConvertSampleCallback) convert_sample_async_callback, &cf_data,
       NULL);
   g_main_loop_run (loop);
-  fail_unless (cf_data.buffer != NULL);
+  fail_unless (cf_data.sample != NULL);
   fail_unless (cf_data.error == NULL);
 
-  gst_buffer_unref (from_buffer);
-  gst_caps_unref (from_caps);
-  gst_buffer_unref (cf_data.buffer);
+  gst_sample_unref (cf_data.sample);
   gst_caps_unref (to_caps);
 
   g_main_loop_unref (loop);
index 9772e8adb401949fc02846a6a16f62e7fff7fc9b..8f8ae0a6d236ea7553642f76f6db8bb450147777 100644 (file)
@@ -19,25 +19,21 @@ typedef struct
 /* called when the appsink notifies us that there is a new buffer ready for
  * processing */
 static void
-on_new_buffer_from_source (GstElement * elt, ProgramData * data)
+on_new_sample_from_sink (GstElement * elt, ProgramData * data)
 {
-  guint size;
+  GstSample *sample;
   GstBuffer *app_buffer, *buffer;
   GstElement *source;
 
-  /* get the buffer from appsink */
-  buffer = gst_app_sink_pull_buffer (GST_APP_SINK (elt));
+  /* get the sample from appsink */
+  sample = gst_app_sink_pull_sample (GST_APP_SINK (elt));
+  buffer = gst_sample_get_buffer (sample);
 
-  /* turn it into an app buffer, it's not really needed, we could simply push
-   * the retrieved buffer from appsink into appsrc just fine.  */
-  size = gst_buffer_get_size (buffer);
-  g_print ("Pushing a buffer of size %d\n", size);
-  app_buffer = gst_buffer_new_and_alloc (size);
+  /* make a copy */
+  app_buffer = gst_buffer_copy (buffer);
 
-  gst_buffer_copy_into (app_buffer, buffer, GST_BUFFER_COPY_MEMORY, 0, size);
-
-  /* we don't need the appsink buffer anymore */
-  gst_buffer_unref (buffer);
+  /* we don't need the appsink sample anymore */
+  gst_sample_unref (sample);
 
   /* get source an push new buffer */
   source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
@@ -134,8 +130,8 @@ main (int argc, char *argv[])
    * push as fast as it can, hence the sync=false */
   testsink = gst_bin_get_by_name (GST_BIN (data->source), "testsink");
   g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync", FALSE, NULL);
-  g_signal_connect (testsink, "new-buffer",
-      G_CALLBACK (on_new_buffer_from_source), data);
+  g_signal_connect (testsink, "new-sample",
+      G_CALLBACK (on_new_sample_from_sink), data);
   gst_object_unref (testsink);
 
   /* setting up sink pipeline, we push audio data into this pipeline that will
index 5468a667cf18ddaae14ea853ec260ad9a46a9937..7dacbbb55636489d554b3ca7e872a2bd7c9be353 100644 (file)
@@ -71,14 +71,14 @@ main (int argc, char *argv[])
   /* _is_eos() does not block and returns TRUE if there is not currently an EOS
    * to be retrieved */
   while (!gst_app_sink_is_eos (GST_APP_SINK (app->sink))) {
-    GstBuffer *buf;
+    GstSample *sample;
 
     /* pull the next item, this can return NULL when there is no more data and
      * EOS has been received */
-    buf = gst_app_sink_pull_buffer (GST_APP_SINK (app->sink));
-    printf ("retrieved buffer %p\n", buf);
-    if (buf)
-      gst_buffer_unref (buf);
+    sample = gst_app_sink_pull_sample (GST_APP_SINK (app->sink));
+    printf ("retrieved sample %p\n", sample);
+    if (sample)
+      gst_sample_unref (sample);
   }
   gst_element_set_state (app->pipe, GST_STATE_NULL);
 
index d06e4dea9e3ab25034ee498d1ec7eb9c0d31850c..86d76635974b927836de42c8a0f88046eee966dc 100644 (file)
@@ -1143,26 +1143,24 @@ volume_notify_cb (GstElement * pipeline, GParamSpec * arg, gpointer user_dat)
 static void
 shot_cb (GtkButton * button, gpointer data)
 {
-  GstBuffer *buffer;
+  GstSample *sample = NULL;
   GstCaps *caps;
 
+  GST_DEBUG ("taking snapshot");
+
   /* convert to our desired format (RGB24) */
-  caps = gst_caps_new_simple ("video/x-raw-rgb",
-      "bpp", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24,
+  caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, "RGB",
       /* Note: we don't ask for a specific width/height here, so that
        * videoscale can adjust dimensions from a non-1/1 pixel aspect
        * ratio to a 1/1 pixel-aspect-ratio */
-      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
-      "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-      "red_mask", G_TYPE_INT, 0xff0000,
-      "green_mask", G_TYPE_INT, 0x00ff00,
-      "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
-
-  /* convert the latest frame to the requested format */
-  g_signal_emit_by_name (pipeline, "convert-frame", caps, &buffer);
+      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
+
+  /* convert the latest sample to the requested format */
+  g_signal_emit_by_name (pipeline, "convert-sample", caps, &sample);
   gst_caps_unref (caps);
 
-  if (buffer) {
+  if (sample) {
+    GstBuffer *buffer;
     GstCaps *caps;
     GstStructure *s;
     gboolean res;
@@ -1176,11 +1174,7 @@ shot_cb (GtkButton * button, gpointer data)
      * that it can only be an rgb buffer. The only thing we have not specified
      * on the caps is the height, which is dependant on the pixel-aspect-ratio
      * of the source material */
-#if 0
-    caps = GST_BUFFER_CAPS (buffer);
-#endif
-    /* FIXME, need to get the caps of the buffer somehow */
-    caps = NULL;
+    caps = gst_sample_get_caps (sample);
     if (!caps) {
       g_warning ("could not get snapshot format\n");
       goto done;
@@ -1197,6 +1191,7 @@ shot_cb (GtkButton * button, gpointer data)
 
     /* create pixmap from buffer and save, gstreamer video buffers have a stride
      * that is rounded up to the nearest multiple of 4 */
+    buffer = gst_sample_get_buffer (sample);
     data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
     pixbuf = gdk_pixbuf_new_from_data (data,
         GDK_COLORSPACE_RGB, FALSE, 8, width, height,
@@ -1207,7 +1202,7 @@ shot_cb (GtkButton * button, gpointer data)
     gst_buffer_unmap (buffer, data, size);
 
   done:
-    gst_buffer_unref (buffer);
+    gst_sample_unref (sample);
   }
 }