summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog27
m---------common0
-rw-r--r--gst-libs/gst/app/.gitignore2
-rw-r--r--gst-libs/gst/app/Makefile.am19
-rw-r--r--gst-libs/gst/app/gstapp-marshal.list1
-rw-r--r--gst-libs/gst/app/gstappsink.c9
-rw-r--r--gst-libs/gst/app/gstappsrc.c450
-rw-r--r--gst-libs/gst/app/gstappsrc.h37
8 files changed, 465 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index 85af9605..25a0a8b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2008-05-07 Wim Taymans <wim.taymans@collabora.co.uk>
+
+ * gst-libs/gst/app/.cvsignore:
+ * gst-libs/gst/app/Makefile.am:
+ * gst-libs/gst/app/gstapp-marshal.list:
+ Add marshal.list, make it compile and add to cvsignore.
+
+ * gst-libs/gst/app/gstappsink.c: (gst_app_sink_dispose),
+ (gst_app_sink_stop):
+ Small cleanups.
+
+ * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init),
+ (gst_app_src_init), (gst_app_src_set_property),
+ (gst_app_src_get_property), (gst_app_src_unlock),
+ (gst_app_src_unlock_stop), (gst_app_src_start), (gst_app_src_stop),
+ (gst_app_src_create), (gst_app_src_set_caps),
+ (gst_app_src_get_caps), (gst_app_src_set_size),
+ (gst_app_src_get_size), (gst_app_src_set_seekable),
+ (gst_app_src_get_seekable), (gst_app_src_set_max_buffers),
+ (gst_app_src_get_max_buffers), (gst_app_src_push_buffer),
+ (gst_app_src_end_of_stream):
+ * gst-libs/gst/app/gstappsrc.h:
+ Beat appsrc in shape, add signals and actions.
+ Add some docs.
+ Add properties for caps, size, seekability and max-buffers.
+ Fix unlock/stop code.
+
2008-05-07 Tim-Philipp Müller <tim.muller at collabora co uk>
* configure.ac:
diff --git a/common b/common
-Subproject 9b28214399156457fd6b43d0604a47e4bdf19c2
+Subproject ba3dd2882b1611f8115f9664e3b85e1fd956b53
diff --git a/gst-libs/gst/app/.gitignore b/gst-libs/gst/app/.gitignore
new file mode 100644
index 00000000..9f0ae4be
--- /dev/null
+++ b/gst-libs/gst/app/.gitignore
@@ -0,0 +1,2 @@
+gstapp-marshal.c
+gstapp-marshal.h
diff --git a/gst-libs/gst/app/Makefile.am b/gst-libs/gst/app/Makefile.am
index 83925c91..d39572aa 100644
--- a/gst-libs/gst/app/Makefile.am
+++ b/gst-libs/gst/app/Makefile.am
@@ -1,6 +1,19 @@
lib_LTLIBRARIES = libgstapp-@GST_MAJORMINOR@.la
-libgstapp_@GST_MAJORMINOR@_la_SOURCES = gstappsrc.c gstappbuffer.c gstappsink.c
+glib_enum_define = GST_APP
+glib_enum_prefix = gst_app
+
+include $(top_srcdir)/common/glib-gen.mak
+
+built_sources = gstapp-marshal.c
+built_headers = gstapp-marshal.h
+
+BUILT_SOURCES = $(built_sources) $(built_headers)
+
+nodist_libgstapp_@GST_MAJORMINOR@_la_SOURCES = \
+ $(built_sources)
+
+libgstapp_@GST_MAJORMINOR@_la_SOURCES = gstappsrc.c gstappbuffer.c gstappsink.c
libgstapp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
$(GST_PLUGINS_BASE_CFLAGS)
libgstapp_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS)
@@ -12,3 +25,7 @@ libgstapp_@GST_MAJORMINOR@include_HEADERS = \
gstappbuffer.h \
gstappsink.h
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = gstapp-marshal.list
+
diff --git a/gst-libs/gst/app/gstapp-marshal.list b/gst-libs/gst/app/gstapp-marshal.list
new file mode 100644
index 00000000..648f363e
--- /dev/null
+++ b/gst-libs/gst/app/gstapp-marshal.list
@@ -0,0 +1 @@
+VOID:UINT64
diff --git a/gst-libs/gst/app/gstappsink.c b/gst-libs/gst/app/gstappsink.c
index 8c5deaa4..cd5779cb 100644
--- a/gst-libs/gst/app/gstappsink.c
+++ b/gst-libs/gst/app/gstappsink.c
@@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2007 David Schleef <ds@schleef.org>
+ * (C) 2008 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -61,7 +62,7 @@ enum
SIGNAL_NEW_PREROLL,
SIGNAL_NEW_BUFFER,
- /* acions */
+ /* actions */
SIGNAL_PULL_PREROLL,
SIGNAL_PULL_BUFFER,
@@ -334,15 +335,18 @@ gst_app_sink_dispose (GObject * obj)
GstAppSink *appsink = GST_APP_SINK (obj);
GstBuffer *buffer;
+ GST_OBJECT_LOCK (appsink);
if (appsink->caps) {
gst_caps_unref (appsink->caps);
appsink->caps = NULL;
}
+ GST_OBJECT_UNLOCK (appsink);
+
+ g_mutex_lock (appsink->mutex);
if (appsink->preroll) {
gst_buffer_unref (appsink->preroll);
appsink->preroll = NULL;
}
- g_mutex_lock (appsink->mutex);
while ((buffer = g_queue_pop_head (appsink->queue)))
gst_buffer_unref (buffer);
g_mutex_unlock (appsink->mutex);
@@ -483,7 +487,6 @@ gst_app_sink_stop (GstBaseSink * psink)
g_mutex_lock (appsink->mutex);
GST_DEBUG_OBJECT (appsink, "stopping");
- appsink->is_eos = FALSE;
appsink->flushing = TRUE;
appsink->started = FALSE;
gst_app_sink_flush_unlocked (appsink);
diff --git a/gst-libs/gst/app/gstappsrc.c b/gst-libs/gst/app/gstappsrc.c
index a3e52af4..c1d01db7 100644
--- a/gst-libs/gst/app/gstappsrc.c
+++ b/gst-libs/gst/app/gstappsrc.c
@@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2007 David Schleef <ds@schleef.org>
+ * (C) 2008 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -26,6 +27,7 @@
#include <string.h>
+#include "gstapp-marshal.h"
#include "gstappsrc.h"
@@ -33,13 +35,37 @@ GST_DEBUG_CATEGORY (app_src_debug);
#define GST_CAT_DEFAULT app_src_debug
static const GstElementDetails app_src_details = GST_ELEMENT_DETAILS ("AppSrc",
- "FIXME",
- "FIXME",
- "autogenerated by makefilter");
+ "Generic/Src",
+ "Allow the application to feed buffers to a pipeline",
+ "David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com");
enum
{
- PROP_0
+ /* signals */
+ SIGNAL_NEED_DATA,
+ SIGNAL_ENOUGH_DATA,
+ SIGNAL_SEEK_DATA,
+
+ /* actions */
+ SIGNAL_PUSH_BUFFER,
+ SIGNAL_END_OF_STREAM,
+
+ LAST_SIGNAL
+};
+
+#define DEFAULT_PROP_MAX_BUFFERS 0
+#define DEFAULT_PROP_SIZE -1
+#define DEFAULT_PROP_SEEKABLE FALSE
+
+enum
+{
+ PROP_0,
+ PROP_CAPS,
+ PROP_SIZE,
+ PROP_SEEKABLE,
+ PROP_MAX_BUFFERS,
+
+ PROP_LAST
};
static GstStaticPadTemplate gst_app_src_template =
@@ -60,6 +86,9 @@ static GstFlowReturn gst_app_src_create (GstPushSrc * psrc, GstBuffer ** buf);
static gboolean gst_app_src_start (GstBaseSrc * psrc);
static gboolean gst_app_src_stop (GstBaseSrc * psrc);
static gboolean gst_app_src_unlock (GstBaseSrc * psrc);
+static gboolean gst_app_src_unlock_stop (GstBaseSrc * psrc);
+
+static guint gst_app_src_signals[LAST_SIGNAL] = { 0 };
GST_BOILERPLATE (GstAppSrc, gst_app_src, GstPushSrc, GST_TYPE_PUSH_SRC);
@@ -89,10 +118,82 @@ gst_app_src_class_init (GstAppSrcClass * klass)
gobject_class->set_property = gst_app_src_set_property;
gobject_class->get_property = gst_app_src_get_property;
+ g_object_class_install_property (gobject_class, PROP_CAPS,
+ g_param_spec_boxed ("caps", "Caps",
+ "The allowed caps for the src pad", GST_TYPE_CAPS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_SIZE,
+ g_param_spec_int64 ("size", "Size",
+ "The size of the data stream (-1 if unknown)",
+ -1, G_MAXINT64, DEFAULT_PROP_SIZE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_SEEKABLE,
+ g_param_spec_boolean ("seekable", "Seekable",
+ "If the source is seekable", DEFAULT_PROP_SEEKABLE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS,
+ g_param_spec_uint ("max-buffers", "Max Buffers",
+ "The maximum number of buffers to queue internally (0 = unlimited)",
+ 0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstAppSrc::need-data:
+ * @appsrc: the appsrc element that emited the signal
+ *
+ * Signal that the source needs more data. In the callback you should call
+ * push-buffer or end-of-stream.
+ */
+ gst_app_src_signals[SIGNAL_NEED_DATA] =
+ g_signal_new ("need-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstAppSrcClass, need_data),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+
+ /**
+ * GstAppSrc::enough-data:
+ * @appsrc: the appsrc element that emited the signal
+ *
+ * Signal that the source has enough data. It is recommended that the
+ * application stops calling push-buffer until the need-data signal is
+ * emited again to avoid excessive buffer queueing.
+ */
+ gst_app_src_signals[SIGNAL_NEED_DATA] =
+ g_signal_new ("enough-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstAppSrcClass, enough_data),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+ /**
+ * GstAppSrc::seek-data:
+ * @appsrc: the appsrc element that emited the signal
+ * @offset: the offset to seek to
+ *
+ * Seek to the given offset. The next push-buffer should produce buffers from
+ * the new @offset.
+ */
+ gst_app_src_signals[SIGNAL_SEEK_DATA] =
+ g_signal_new ("seek-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstAppSrcClass, seek_data),
+ NULL, NULL, gst_app_marshal_VOID__UINT64, G_TYPE_NONE, 1, G_TYPE_UINT64);
+
+ gst_app_src_signals[SIGNAL_PUSH_BUFFER] =
+ g_signal_new ("push-buffer", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSrcClass,
+ push_buffer), NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GST_TYPE_BUFFER);
+
+ gst_app_src_signals[SIGNAL_END_OF_STREAM] =
+ g_signal_new ("end-of-stream", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSrcClass,
+ end_of_stream), NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0, G_TYPE_NONE);
+
pushsrc_class->create = gst_app_src_create;
basesrc_class->start = gst_app_src_start;
basesrc_class->stop = gst_app_src_stop;
basesrc_class->unlock = gst_app_src_unlock;
+ basesrc_class->unlock_stop = gst_app_src_unlock_stop;
}
static void
@@ -101,6 +202,10 @@ gst_app_src_init (GstAppSrc * appsrc, GstAppSrcClass * klass)
appsrc->mutex = g_mutex_new ();
appsrc->cond = g_cond_new ();
appsrc->queue = g_queue_new ();
+
+ appsrc->size = DEFAULT_PROP_SIZE;
+ appsrc->seekable = DEFAULT_PROP_SEEKABLE;
+ appsrc->max_buffers = DEFAULT_PROP_MAX_BUFFERS;
}
static void
@@ -134,13 +239,23 @@ gst_app_src_set_property (GObject * object, guint prop_id,
{
GstAppSrc *appsrc = GST_APP_SRC (object);
- GST_OBJECT_LOCK (appsrc);
switch (prop_id) {
+ case PROP_CAPS:
+ gst_app_src_set_caps (appsrc, gst_value_get_caps (value));
+ break;
+ case PROP_SIZE:
+ gst_app_src_set_size (appsrc, g_value_get_int64 (value));
+ break;
+ case PROP_SEEKABLE:
+ gst_app_src_set_seekable (appsrc, g_value_get_boolean (value));
+ break;
+ case PROP_MAX_BUFFERS:
+ gst_app_src_set_max_buffers (appsrc, g_value_get_uint (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
- GST_OBJECT_UNLOCK (appsrc);
}
static void
@@ -149,46 +264,84 @@ gst_app_src_get_property (GObject * object, guint prop_id, GValue * value,
{
GstAppSrc *appsrc = GST_APP_SRC (object);
- GST_OBJECT_LOCK (appsrc);
switch (prop_id) {
+ case PROP_CAPS:
+ {
+ GstCaps *caps;
+
+ caps = gst_app_src_get_caps (appsrc);
+ gst_value_set_caps (value, caps);
+ if (caps)
+ gst_caps_unref (caps);
+ break;
+ }
+ case PROP_SIZE:
+ g_value_set_int64 (value, gst_app_src_get_size (appsrc));
+ break;
+ case PROP_SEEKABLE:
+ g_value_set_boolean (value, gst_app_src_get_seekable (appsrc));
+ break;
+ case PROP_MAX_BUFFERS:
+ g_value_set_uint (value, gst_app_src_get_max_buffers (appsrc));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
- GST_OBJECT_UNLOCK (appsrc);
}
static gboolean
-gst_app_src_start (GstBaseSrc * psrc)
+gst_app_src_unlock (GstBaseSrc * psrc)
{
GstAppSrc *appsrc = GST_APP_SRC (psrc);
- appsrc->unlock = FALSE;
+ g_mutex_lock (appsrc->mutex);
+ GST_DEBUG_OBJECT (appsrc, "unlock start");
+ appsrc->flushing = TRUE;
+ g_cond_signal (appsrc->cond);
+ g_mutex_unlock (appsrc->mutex);
-#if 0
- /* FIXME: I don't know if this makes sense */
- appsrc->end_of_stream = FALSE;
- appsrc->flush = FALSE;
-#endif
+ return TRUE;
+}
+
+static gboolean
+gst_app_src_unlock_stop (GstBaseSrc * psrc)
+{
+ GstAppSrc *appsrc = GST_APP_SRC (psrc);
+
+ g_mutex_lock (appsrc->mutex);
+ GST_DEBUG_OBJECT (appsrc, "unlock stop");
+ appsrc->flushing = FALSE;
+ g_cond_signal (appsrc->cond);
+ g_mutex_unlock (appsrc->mutex);
return TRUE;
}
static gboolean
-gst_app_src_stop (GstBaseSrc * psrc)
+gst_app_src_start (GstBaseSrc * psrc)
{
- //GstAppSrc *appsrc = GST_APP_SRC(psrc);
+ GstAppSrc *appsrc = GST_APP_SRC (psrc);
+
+ g_mutex_lock (appsrc->mutex);
+ GST_DEBUG_OBJECT (appsrc, "starting");
+ appsrc->started = TRUE;
+ g_mutex_unlock (appsrc->mutex);
return TRUE;
}
static gboolean
-gst_app_src_unlock (GstBaseSrc * psrc)
+gst_app_src_stop (GstBaseSrc * psrc)
{
GstAppSrc *appsrc = GST_APP_SRC (psrc);
- appsrc->unlock = TRUE;
- g_cond_signal (appsrc->cond);
+ g_mutex_lock (appsrc->mutex);
+ GST_DEBUG_OBJECT (appsrc, "stopping");
+ appsrc->is_eos = FALSE;
+ appsrc->flushing = TRUE;
+ appsrc->started = FALSE;
+ g_mutex_unlock (appsrc->mutex);
return TRUE;
}
@@ -197,104 +350,264 @@ static GstFlowReturn
gst_app_src_create (GstPushSrc * psrc, GstBuffer ** buf)
{
GstAppSrc *appsrc = GST_APP_SRC (psrc);
- int ret = GST_FLOW_ERROR;
+ GstFlowReturn ret;
g_mutex_lock (appsrc->mutex);
+ while (TRUE) {
+ /* check flushing first */
+ if (appsrc->flushing)
+ goto flushing;
- while (1) {
- if (appsrc->unlock) {
- ret = GST_FLOW_WRONG_STATE;
- break;
- }
+ /* return data as long as we have some */
if (!g_queue_is_empty (appsrc->queue)) {
*buf = g_queue_pop_head (appsrc->queue);
gst_buffer_set_caps (*buf, appsrc->caps);
+ GST_DEBUG_OBJECT (appsrc, "we have buffer %p", *buf);
ret = GST_FLOW_OK;
break;
}
- if (appsrc->end_of_stream) {
- appsrc->end_of_stream = FALSE;
- ret = GST_FLOW_UNEXPECTED;
- break;
- }
- if (appsrc->flush) {
- appsrc->flush = FALSE;
- /* FIXME: I don't really know how to do this */
- break;
- }
+
+ /* check EOS */
+ if (appsrc->is_eos)
+ goto eos;
+
+ /* nothing to return, wait a while for new data or flushing */
g_cond_wait (appsrc->cond, appsrc->mutex);
}
-
g_mutex_unlock (appsrc->mutex);
return ret;
+
+ /* ERRORS */
+flushing:
+ {
+ GST_DEBUG_OBJECT (appsrc, "we are flushing");
+ g_mutex_unlock (appsrc->mutex);
+ return GST_FLOW_WRONG_STATE;
+ }
+eos:
+ {
+ GST_DEBUG_OBJECT (appsrc, "we are EOS");
+ g_mutex_unlock (appsrc->mutex);
+ return GST_FLOW_UNEXPECTED;
+ }
}
/* external API */
/**
- * gst_app_src_push_buffer:
- * @appsrc:
- * @buffer:
+ * gst_app_src_set_caps:
+ * @appsrc: a #GstAppSrc
+ * @caps: caps to set
*
- * Adds a buffer to the queue of buffers that the appsrc element will
- * push to its source pad. This function takes ownership of the buffer.
+ * Set the capabilities on the appsrc element. This function takes
+ * a copy of the caps structure. After calling this method, the source will
+ * only produce caps that match @caps. @caps must be fixed and the caps on the
+ * buffers must match the caps or left NULL.
*/
void
-gst_app_src_push_buffer (GstAppSrc * appsrc, GstBuffer * buffer)
+gst_app_src_set_caps (GstAppSrc * appsrc, const GstCaps * caps)
{
- g_return_if_fail (appsrc);
+ GstCaps *old;
+
g_return_if_fail (GST_IS_APP_SRC (appsrc));
- g_mutex_lock (appsrc->mutex);
+ GST_OBJECT_LOCK (appsrc);
+ GST_DEBUG_OBJECT (appsrc, "setting caps to %" GST_PTR_FORMAT, caps);
+ if ((old = appsrc->caps) != caps) {
+ if (caps)
+ appsrc->caps = gst_caps_copy (caps);
+ else
+ appsrc->caps = NULL;
+ if (old)
+ gst_caps_unref (old);
+ }
+ GST_OBJECT_UNLOCK (appsrc);
+}
- g_queue_push_tail (appsrc->queue, buffer);
+/**
+ * gst_app_src_get_caps:
+ * @appsrc: a #GstAppSrc
+ *
+ * Get the configured caps on @appsrc.
+ *
+ * Returns: the #GstCaps produced by the source. gst_caps_unref() after usage.
+ */
+GstCaps *
+gst_app_src_get_caps (GstAppSrc * appsrc)
+{
+ GstCaps *caps;
- g_cond_signal (appsrc->cond);
- g_mutex_unlock (appsrc->mutex);
+ g_return_val_if_fail (appsrc != NULL, NULL);
+ g_return_val_if_fail (GST_IS_APP_SRC (appsrc), NULL);
+
+ GST_OBJECT_LOCK (appsrc);
+ if ((caps = appsrc->caps))
+ gst_caps_ref (caps);
+ GST_DEBUG_OBJECT (appsrc, "getting caps of %" GST_PTR_FORMAT, caps);
+ GST_OBJECT_UNLOCK (appsrc);
+
+ return caps;
}
/**
- * gst_app_src_set_caps:
- * @appsrc:
- * @caps:
+ * gst_app_src_set_size:
+ * @appsrc: a #GstAppSrc
+ * @size: the size to set
*
- * Set the capabilities on the appsrc element. This function takes
- * ownership of the caps structure.
+ * Set the size of the stream in bytes. A value of -1 means that the size is
+ * not known.
*/
void
-gst_app_src_set_caps (GstAppSrc * appsrc, GstCaps * caps)
+gst_app_src_set_size (GstAppSrc * appsrc, gint64 size)
{
- g_return_if_fail (appsrc);
+ g_return_if_fail (appsrc != NULL);
g_return_if_fail (GST_IS_APP_SRC (appsrc));
- gst_caps_replace (&appsrc->caps, caps);
+ GST_OBJECT_LOCK (appsrc);
+ GST_DEBUG_OBJECT (appsrc, "setting size of %" G_GINT64_FORMAT, size);
+ appsrc->size = size;
+ GST_OBJECT_UNLOCK (appsrc);
}
/**
- * gst_app_src_flush:
- * @appsrc:
+ * gst_app_src_get_size:
+ * @appsrc: a #GstAppSrc
*
- * Flushes all queued buffers from the appsrc element.
+ * Get the size of the stream in bytes. A value of -1 means that the size is
+ * not known.
+ *
+ * Returns: the size of the stream previously set with gst_app_src_set_size();
+ */
+gint64
+gst_app_src_get_size (GstAppSrc * appsrc)
+{
+ gint64 size;
+
+ g_return_val_if_fail (appsrc != NULL, -1);
+ g_return_val_if_fail (GST_IS_APP_SRC (appsrc), -1);
+
+ GST_OBJECT_LOCK (appsrc);
+ size = appsrc->size;
+ GST_DEBUG_OBJECT (appsrc, "getting size of %" G_GINT64_FORMAT, size);
+ GST_OBJECT_UNLOCK (appsrc);
+
+ return size;
+}
+
+/**
+ * gst_app_src_set_seekable:
+ * @appsrc: a #GstAppSrc
+ * @seekable: the new state
+ *
+ * Set whether the data is seekable. When this flag is set to %TRUE, the
+ * "seek" signal must be connected to.
*/
void
-gst_app_src_flush (GstAppSrc * appsrc)
+gst_app_src_set_seekable (GstAppSrc * appsrc, gboolean seekable)
{
- GstBuffer *buffer;
+ g_return_if_fail (appsrc != NULL);
+ g_return_if_fail (GST_IS_APP_SRC (appsrc));
- g_return_if_fail (appsrc);
+ GST_OBJECT_LOCK (appsrc);
+ GST_DEBUG_OBJECT (appsrc, "setting seekable of %d", seekable);
+ appsrc->seekable = seekable;
+ GST_OBJECT_UNLOCK (appsrc);
+}
+
+/**
+ * gst_app_src_get_seekable:
+ * @appsrc: a #GstAppSrc
+ *
+ * Get whether the stream is seekable. Control the seeking behaviour of the
+ * stream with gst_app_src_set_seekable().
+ *
+ * Returns: %TRUE if the stream is seekable.
+ */
+gboolean
+gst_app_src_get_seekable (GstAppSrc * appsrc)
+{
+ gboolean seekable;
+
+ g_return_val_if_fail (appsrc != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_APP_SRC (appsrc), FALSE);
+
+ GST_OBJECT_LOCK (appsrc);
+ seekable = appsrc->seekable;
+ GST_DEBUG_OBJECT (appsrc, "getting seekable of %d", seekable);
+ GST_OBJECT_UNLOCK (appsrc);
+
+ return seekable;
+}
+
+/**
+ * gst_app_src_set_max_buffers:
+ * @appsrc: a #GstAppSrc
+ * @max: the maximum number of buffers to queue
+ *
+ * Set the maximum amount of buffers that can be queued in @appsrc.
+ * After the maximum amount of buffers are queued, @appsrc will emit the
+ * "enough-data" signal.
+ */
+void
+gst_app_src_set_max_buffers (GstAppSrc * appsrc, guint max)
+{
g_return_if_fail (GST_IS_APP_SRC (appsrc));
g_mutex_lock (appsrc->mutex);
-
- while ((buffer = g_queue_pop_head (appsrc->queue))) {
- gst_buffer_unref (buffer);
+ if (max != appsrc->max_buffers) {
+ GST_DEBUG_OBJECT (appsrc, "setting max-buffers to %u", max);
+ appsrc->max_buffers = max;
+ /* signal the change */
+ g_cond_signal (appsrc->cond);
}
- appsrc->flush = TRUE;
+ g_mutex_unlock (appsrc->mutex);
+}
+
+/**
+ * gst_app_src_get_max_buffers:
+ * @appsrc: a #GstAppSrc
+ *
+ * Get the maximum amount of buffers that can be queued in @appsrc.
+ *
+ * Returns: The maximum amount of buffers that can be queued.
+ */
+guint
+gst_app_src_get_max_buffers (GstAppSrc * appsrc)
+{
+ guint result;
+
+ g_return_val_if_fail (GST_IS_APP_SRC (appsrc), 0);
+
+ g_mutex_lock (appsrc->mutex);
+ result = appsrc->max_buffers;
+ GST_DEBUG_OBJECT (appsrc, "getting max-buffers of %u", result);
+ g_mutex_unlock (appsrc->mutex);
+ return result;
+}
+
+/**
+ * gst_app_src_push_buffer:
+ * @appsrc:
+ * @buffer:
+ *
+ * Adds a buffer to the queue of buffers that the appsrc element will
+ * push to its source pad. This function takes ownership of the buffer.
+ */
+void
+gst_app_src_push_buffer (GstAppSrc * appsrc, GstBuffer * buffer)
+{
+ g_return_if_fail (appsrc);
+ g_return_if_fail (GST_IS_APP_SRC (appsrc));
+ g_return_if_fail (GST_IS_BUFFER (buffer));
+
+ g_mutex_lock (appsrc->mutex);
+ GST_DEBUG_OBJECT (appsrc, "queueing buffer %p", buffer);
+ g_queue_push_tail (appsrc->queue, buffer);
g_cond_signal (appsrc->cond);
g_mutex_unlock (appsrc->mutex);
}
@@ -313,9 +626,8 @@ gst_app_src_end_of_stream (GstAppSrc * appsrc)
g_return_if_fail (GST_IS_APP_SRC (appsrc));
g_mutex_lock (appsrc->mutex);
-
- appsrc->end_of_stream = TRUE;
-
+ GST_DEBUG_OBJECT (appsrc, "sending EOS");
+ appsrc->is_eos = TRUE;
g_cond_signal (appsrc->cond);
g_mutex_unlock (appsrc->mutex);
}
diff --git a/gst-libs/gst/app/gstappsrc.h b/gst-libs/gst/app/gstappsrc.h
index 617a20e2..4ca5cbc9 100644
--- a/gst-libs/gst/app/gstappsrc.h
+++ b/gst-libs/gst/app/gstappsrc.h
@@ -44,29 +44,52 @@ struct _GstAppSrc
GstPushSrc pushsrc;
/*< private >*/
- gboolean unlock;
GCond *cond;
GMutex *mutex;
GQueue *queue;
+
GstCaps *caps;
- gboolean end_of_stream;
- gboolean flush;
+ gint64 size;
+ gboolean seekable;
+ guint max_buffers;
+
+ gboolean flushing;
+ gboolean started;
+ gboolean is_eos;
};
struct _GstAppSrcClass
{
GstPushSrcClass pushsrc_class;
+
+ /* signals */
+ void (*need_data) (GstAppSrc *src);
+ void (*enough_data) (GstAppSrc *src);
+ gboolean (*seek_data) (GstAppSrc *src, guint64 offset);
+
+ /* actions */
+ void (*push_buffer) (GstAppSrc *src, GstBuffer *buffer);
+ void (*end_of_stream) (GstAppSrc *src);
};
GType gst_app_src_get_type(void);
GST_DEBUG_CATEGORY_EXTERN (app_src_debug);
+void gst_app_src_set_caps (GstAppSrc *appsrc, const GstCaps *caps);
+GstCaps* gst_app_src_get_caps (GstAppSrc *appsrc);
+
+void gst_app_src_set_size (GstAppSrc *appsrc, gint64 size);
+gint64 gst_app_src_get_size (GstAppSrc *appsrc);
+
+void gst_app_src_set_seekable (GstAppSrc *appsrc, gboolean seekable);
+gboolean gst_app_src_get_seekable (GstAppSrc *appsrc);
+
+void gst_app_src_set_max_buffers (GstAppSrc *appsrc, guint max);
+guint gst_app_src_get_max_buffers (GstAppSrc *appsrc);
-void gst_app_src_push_buffer (GstAppSrc *appsrc, GstBuffer *buffer);
-void gst_app_src_set_caps (GstAppSrc *appsrc, GstCaps *caps);
-void gst_app_src_flush (GstAppSrc *appsrc);
-void gst_app_src_end_of_stream (GstAppSrc *appsrc);
+void gst_app_src_push_buffer (GstAppSrc *appsrc, GstBuffer *buffer);
+void gst_app_src_end_of_stream (GstAppSrc *appsrc);
G_END_DECLS