summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
Diffstat (limited to 'gst-libs')
-rw-r--r--gst-libs/gst/app/gstappsink.c536
-rw-r--r--gst-libs/gst/app/gstappsink.h31
-rw-r--r--gst-libs/gst/audio/gstaudiobasesink.c2
-rw-r--r--gst-libs/gst/video/convertframe.c140
-rw-r--r--gst-libs/gst/video/video.h12
5 files changed, 312 insertions, 409 deletions
diff --git a/gst-libs/gst/app/gstappsink.c b/gst-libs/gst/app/gstappsink.c
index 3bfcd596a..5cb3d3903 100644
--- a/gst-libs/gst/app/gstappsink.c
+++ b/gst-libs/gst/app/gstappsink.c
@@ -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
@@ -30,13 +30,13 @@
* 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
@@ -44,14 +44,14 @@
* 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.
*
@@ -70,16 +70,17 @@
#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);
}
diff --git a/gst-libs/gst/app/gstappsink.h b/gst-libs/gst/app/gstappsink.h
index 4bca82b67..5259dec6c 100644
--- a/gst-libs/gst/app/gstappsink.h
+++ b/gst-libs/gst/app/gstappsink.h
@@ -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,
diff --git a/gst-libs/gst/audio/gstaudiobasesink.c b/gst-libs/gst/audio/gstaudiobasesink.c
index d7c1090a4..19a1c6536 100644
--- a/gst-libs/gst/audio/gstaudiobasesink.c
+++ b/gst-libs/gst/audio/gstaudiobasesink.c
@@ -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
diff --git a/gst-libs/gst/video/convertframe.c b/gst-libs/gst/video/convertframe.c
index 663924822..73dcfb1fc 100644
--- a/gst-libs/gst/video/convertframe.c
+++ b/gst-libs/gst/video/convertframe.c
@@ -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);
diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h
index 42a2024e4..57dff7ac6 100644
--- a/gst-libs/gst/video/video.h
+++ b/gst-libs/gst/video/video.h
@@ -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);