summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2005-03-04 10:16:10 +0000
committerWim Taymans <wim.taymans@gmail.com>2005-03-04 10:16:10 +0000
commit45a98d955f29791a5430de4fe9f4b1b1773ef4a7 (patch)
tree4858adcaa0e518ebc6e27a26dc0f1e0b517c8854
parent78f028541ce4589779797e32172ab3d7400a9be8 (diff)
More work on subclassing the sinks from the basesink.BRANCH-THREADED
Original commit message from CVS: More work on subclassing the sinks from the basesink. First attempt at generic audiosink base objects. Make oss DMA audiosink.
-rw-r--r--ChangeLog61
-rw-r--r--examples/seeking/seek.c2
-rw-r--r--gst-libs/gst/audio/Makefile.am6
-rw-r--r--gst-libs/gst/audio/gstbaseaudiosink.c235
-rw-r--r--gst-libs/gst/audio/gstbaseaudiosink.h87
-rw-r--r--gst-libs/gst/audio/gstringbuffer.c282
-rw-r--r--gst-libs/gst/audio/gstringbuffer.h114
-rw-r--r--gst-libs/gst/video/Makefile.am2
-rw-r--r--gst-libs/gst/video/gstvideosink.c16
-rw-r--r--gst-libs/gst/video/videosink.h13
10 files changed, 792 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index fd5501f1..53dc38e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+2005-03-04 Wim Taymans <wim@fluendo.com>
+
+ * examples/seeking/seek.c:
+ * ext/theora/theoraenc.c: (theora_enc_sink_event),
+ (theora_enc_chain):
+ * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event),
+ (gst_vorbisenc_chain):
+ * gst-libs/gst/audio/Makefile.am:
+ * gst-libs/gst/audio/gstbaseaudiosink.c:
+ (gst_baseaudiosink_base_init), (gst_baseaudiosink_class_init),
+ (gst_baseaudiosink_init), (gst_baseaudiosink_set_property),
+ (gst_baseaudiosink_get_property), (gst_baseaudiosink_setcaps),
+ (gst_baseaudiosink_get_times), (gst_baseaudiosink_event),
+ (gst_baseaudiosink_preroll), (gst_baseaudiosink_render),
+ (gst_baseaudiosink_create_ringbuffer),
+ (gst_baseaudiosink_callback), (gst_baseaudiosink_change_state):
+ * gst-libs/gst/audio/gstbaseaudiosink.h:
+ * gst-libs/gst/audio/gstringbuffer.c: (gst_ringbuffer_get_type),
+ (gst_ringbuffer_class_init), (gst_ringbuffer_init),
+ (gst_ringbuffer_dispose), (gst_ringbuffer_finalize),
+ (gst_ringbuffer_set_callback), (gst_ringbuffer_acquire),
+ (gst_ringbuffer_release), (gst_ringbuffer_play),
+ (gst_ringbuffer_stop), (gst_ringbuffer_callback),
+ (gst_ringbuffer_write):
+ * gst-libs/gst/audio/gstringbuffer.h:
+ * gst-libs/gst/video/Makefile.am:
+ * gst-libs/gst/video/gstvideosink.c: (gst_videosink_init),
+ (gst_videosink_class_init), (gst_videosink_get_type):
+ * gst-libs/gst/video/videosink.h:
+ * sys/oss/Makefile.am:
+ * sys/oss/gstossdmabuffer.c: (gst_ossdmabuffer_get_type),
+ (gst_ossdmabuffer_class_init), (gst_ossdmabuffer_init),
+ (gst_ossdmabuffer_dispose), (gst_ossdmabuffer_finalize),
+ (gst_ossdmabuffer_func), (gst_ossdmabuffer_acquire),
+ (gst_ossdmabuffer_release), (gst_ossdmabuffer_play),
+ (gst_ossdmabuffer_stop):
+ * sys/oss/gstossdmabuffer.h:
+ * sys/oss/gstosselement.c: (gst_osselement_class_init),
+ (gst_osselement_parse_caps), (gst_osselement_sync_parms),
+ (gst_osselement_open_audio):
+ * sys/oss/gstosselement.h:
+ * sys/oss/gstosssink.c: (gst_osssink_get_type),
+ (gst_osssink_gettemplate), (gst_osssink_class_init),
+ (gst_osssink_init), (gst_osssink_getcaps), (gst_osssink_get_delay),
+ (gst_osssink_get_time), (gst_osssink_create_ringbuffer),
+ (gst_osssink_render), (gst_osssink_convert),
+ (gst_osssink_sink_query), (gst_osssink_query),
+ (gst_osssink_set_property), (gst_osssink_get_property),
+ (gst_osssink_change_state):
+ * sys/oss/gstosssink.h:
+ * sys/xvimage/xvimagesink.c: (gst_xvimagesink_getcaps),
+ (gst_xvimagesink_setcaps), (gst_xvimagesink_change_state),
+ (gst_xvimagesink_get_times), (gst_xvimagesink_show_frame),
+ (gst_xvimagesink_chain), (gst_xvimagesink_buffer_alloc),
+ (gst_xvimagesink_init), (gst_xvimagesink_get_template),
+ (gst_xvimagesink_class_init):
+ * sys/xvimage/xvimagesink.h:
+ More work on subclassing the sinks from the basesink.
+ First attempt at generic audiosink base objects.
+ Make oss DMA audiosink.
+
2005-02-20 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/avi/gstavidemux.c: (gst_avi_demux_index_next),
diff --git a/examples/seeking/seek.c b/examples/seeking/seek.c
index 81ba7d8f..ef73db6b 100644
--- a/examples/seeking/seek.c
+++ b/examples/seeking/seek.c
@@ -27,7 +27,7 @@ static gulong changed_id;
/* number of milliseconds to play for after a seek */
#define SCRUB_TIME 250
-#undef SCRUB
+#define SCRUB
#define THREAD
#define PAD_SEEK
diff --git a/gst-libs/gst/audio/Makefile.am b/gst-libs/gst/audio/Makefile.am
index 99089947..9bf04c2c 100644
--- a/gst-libs/gst/audio/Makefile.am
+++ b/gst-libs/gst/audio/Makefile.am
@@ -17,7 +17,9 @@ CLEANFILES = gstaudiofilterexample.c \
$(BUILT_SOURCES)
libgstaudio_la_SOURCES = audio.c audioclock.c \
- multichannel.c
+ multichannel.c \
+ gstbaseaudiosink.c \
+ gstringbuffer.c
nodist_libgstaudio_la_SOURCES = $(built_sources)
libgstaudioincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/audio
@@ -25,6 +27,8 @@ libgstaudioinclude_HEADERS = \
audio.h \
audioclock.h \
gstaudiofilter.h \
+ gstbaseaudiosink.h \
+ gstringbuffer.h \
multichannel.h \
multichannel-enumtypes.h
diff --git a/gst-libs/gst/audio/gstbaseaudiosink.c b/gst-libs/gst/audio/gstbaseaudiosink.c
new file mode 100644
index 00000000..d27b4a22
--- /dev/null
+++ b/gst-libs/gst/audio/gstbaseaudiosink.c
@@ -0,0 +1,235 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstbaseaudiosink.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gstbaseaudiosink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_baseaudiosink_debug);
+#define GST_CAT_DEFAULT gst_baseaudiosink_debug
+
+/* BaseAudioSink signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0,
+};
+
+#define _do_init(bla) \
+ GST_DEBUG_CATEGORY_INIT (gst_baseaudiosink_debug, "baseaudiosink", 0, "baseaudiosink element");
+
+GST_BOILERPLATE_FULL (GstBaseAudioSink, gst_baseaudiosink, GstBaseSink,
+ GST_TYPE_BASESINK, _do_init);
+
+static void gst_baseaudiosink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_baseaudiosink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstElementStateReturn gst_baseaudiosink_change_state (GstElement *
+ element);
+
+static GstFlowReturn gst_baseaudiosink_preroll (GstBaseSink * bsink,
+ GstBuffer * buffer);
+static GstFlowReturn gst_baseaudiosink_render (GstBaseSink * bsink,
+ GstBuffer * buffer);
+static void gst_baseaudiosink_event (GstBaseSink * bsink, GstEvent * event);
+static void gst_baseaudiosink_get_times (GstBaseSink * bsink,
+ GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
+static gboolean gst_baseaudiosink_setcaps (GstBaseSink * bsink, GstCaps * caps);
+
+//static guint gst_baseaudiosink_signals[LAST_SIGNAL] = { 0 };
+
+static void
+gst_baseaudiosink_base_init (gpointer g_class)
+{
+}
+
+static void
+gst_baseaudiosink_class_init (GstBaseAudioSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+
+ gobject_class->set_property =
+ GST_DEBUG_FUNCPTR (gst_baseaudiosink_set_property);
+ gobject_class->get_property =
+ GST_DEBUG_FUNCPTR (gst_baseaudiosink_get_property);
+
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_baseaudiosink_change_state);
+
+ gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_baseaudiosink_event);
+ gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_baseaudiosink_preroll);
+ gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_baseaudiosink_render);
+ gstbasesink_class->get_times =
+ GST_DEBUG_FUNCPTR (gst_baseaudiosink_get_times);
+ gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_baseaudiosink_setcaps);
+}
+
+static void
+gst_baseaudiosink_init (GstBaseAudioSink * baseaudiosink)
+{
+}
+
+static void
+gst_baseaudiosink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstBaseAudioSink *sink;
+
+ sink = GST_BASEAUDIOSINK (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_baseaudiosink_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstBaseAudioSink *sink;
+
+ sink = GST_BASEAUDIOSINK (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gst_baseaudiosink_setcaps (GstBaseSink * bsink, GstCaps * caps)
+{
+ GstBaseAudioSink *sink = GST_BASEAUDIOSINK (bsink);
+ GstRingBufferSpec spec;
+
+ spec.caps = caps;
+ spec.segsize = 64;
+ spec.segtotal = 64;
+
+ gst_ringbuffer_release (sink->ringbuffer);
+ gst_ringbuffer_acquire (sink->ringbuffer, &spec);
+
+ return TRUE;
+}
+
+static void
+gst_baseaudiosink_get_times (GstBaseSink * bsink, GstBuffer * buffer,
+ GstClockTime * start, GstClockTime * end)
+{
+ *start = GST_CLOCK_TIME_NONE;
+ *end = GST_CLOCK_TIME_NONE;
+}
+
+static void
+gst_baseaudiosink_event (GstBaseSink * bsink, GstEvent * event)
+{
+}
+
+static GstFlowReturn
+gst_baseaudiosink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
+{
+ return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_baseaudiosink_render (GstBaseSink * bsink, GstBuffer * buf)
+{
+ GstBaseAudioSink *sink = GST_BASEAUDIOSINK (bsink);
+
+ gst_ringbuffer_write (sink->ringbuffer, GST_CLOCK_TIME_NONE,
+ GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+
+ return GST_FLOW_OK;
+}
+
+GstRingBuffer *
+gst_baseaudiosink_create_ringbuffer (GstBaseAudioSink * sink)
+{
+ GstBaseAudioSinkClass *bclass;
+ GstRingBuffer *buffer = NULL;
+
+ bclass = GST_BASEAUDIOSINK_GET_CLASS (sink);
+ if (bclass->create_ringbuffer)
+ buffer = bclass->create_ringbuffer (sink);
+
+ return buffer;
+}
+
+void
+gst_baseaudiosink_callback (GstRingBuffer * rbuf, guint advance, gpointer data)
+{
+ //GstBaseAudioSink *sink = GST_BASEAUDIOSINK (data);
+}
+
+static GstElementStateReturn
+gst_baseaudiosink_change_state (GstElement * element)
+{
+ GstElementStateReturn ret = GST_STATE_SUCCESS;
+ GstBaseAudioSink *sink = GST_BASEAUDIOSINK (element);
+ GstElementState transition = GST_STATE_TRANSITION (element);
+
+ switch (transition) {
+ case GST_STATE_NULL_TO_READY:
+ break;
+ case GST_STATE_READY_TO_PAUSED:
+ sink->ringbuffer = gst_baseaudiosink_create_ringbuffer (sink);
+ gst_ringbuffer_set_callback (sink->ringbuffer, gst_baseaudiosink_callback,
+ sink);
+ break;
+ case GST_STATE_PAUSED_TO_PLAYING:
+ gst_ringbuffer_play (sink->ringbuffer);
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ switch (transition) {
+ case GST_STATE_PLAYING_TO_PAUSED:
+ gst_ringbuffer_stop (sink->ringbuffer);
+ break;
+ case GST_STATE_PAUSED_TO_READY:
+ gst_object_unref (GST_OBJECT (sink->ringbuffer));
+ break;
+ case GST_STATE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
diff --git a/gst-libs/gst/audio/gstbaseaudiosink.h b/gst-libs/gst/audio/gstbaseaudiosink.h
new file mode 100644
index 00000000..cd8bb61a
--- /dev/null
+++ b/gst-libs/gst/audio/gstbaseaudiosink.h
@@ -0,0 +1,87 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstbaseaudosink.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* a base class for audio sinks.
+ *
+ * It uses a ringbuffer to schedule playback of samples. This makes
+ * it very easy to drop or insert samples to align incomming
+ * buffers to the exact playback timestamp.
+ *
+ * Subclasses must provide a ringbuffer pointing to either DMA
+ * memory or regular memory. A subclass should also call a callback
+ * function when it has processed N samples in the buffer. The subclass
+ * is free to use a thread to signal this callback, use EIO or any
+ * other mechanism.
+ *
+ * The base class is able to operate in push or pull mode. The chain
+ * mode will queue the samples in the ringbuffer as much as possible.
+ * The available space is calculated in the callback function.
+ *
+ * The pull mode will pull_range() a new buffer of N samples with a
+ * configurable latency. This allows for high-end real time
+ * audio processing pipelines driven by the audiosink. The callback
+ * function will be used to perform a pull_range() on the sinkpad.
+ * The thread scheduling the callback can be a real-time thread.
+ */
+
+#ifndef __GST_BASEAUDIOSINK_H__
+#define __GST_BASEAUDIOSINK_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
+#include "gstringbuffer.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_BASEAUDIOSINK (gst_baseaudiosink_get_type())
+#define GST_BASEAUDIOSINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASEAUDIOSINK,GstBaseAudioSink))
+#define GST_BASEAUDIOSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASEAUDIOSINK,GstBaseAudioSinkClass))
+#define GST_BASEAUDIOSINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASEAUDIOSINK, GstBaseAudioSinkClass))
+#define GST_IS_BASEAUDIOSINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASEAUDIOSINK))
+#define GST_IS_BASEAUDIOSINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASEAUDIOSINK))
+
+#define GST_BASEAUDIOSINK_CLOCK(obj) (GST_BASEAUDIOSINK (obj)->clock)
+#define GST_BASEAUDIOSINK_PAD(obj) (GST_BASEAUDIOSINK (obj)->sinkpad)
+
+typedef struct _GstBaseAudioSink GstBaseAudioSink;
+typedef struct _GstBaseAudioSinkClass GstBaseAudioSinkClass;
+
+struct _GstBaseAudioSink {
+ GstBaseSink element;
+
+ GstRingBuffer *ringbuffer;
+};
+
+struct _GstBaseAudioSinkClass {
+ GstBaseSinkClass parent_class;
+
+ /* subclass ringbuffer allocation */
+ GstRingBuffer* (*create_ringbuffer) (GstBaseAudioSink *sink);
+};
+
+GType gst_baseaudiosink_get_type(void);
+
+GstRingBuffer *gst_baseaudiosink_create_ringbuffer (GstBaseAudioSink *sink);
+
+G_END_DECLS
+
+#endif /* __GST_BASEAUDIOSINK_H__ */
diff --git a/gst-libs/gst/audio/gstringbuffer.c b/gst-libs/gst/audio/gstringbuffer.c
new file mode 100644
index 00000000..07889db2
--- /dev/null
+++ b/gst-libs/gst/audio/gstringbuffer.c
@@ -0,0 +1,282 @@
+/* GStreamer
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstringbuffer.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+
+#include "gstringbuffer.h"
+
+static void gst_ringbuffer_class_init (GstRingBufferClass * klass);
+static void gst_ringbuffer_init (GstRingBuffer * ringbuffer);
+static void gst_ringbuffer_dispose (GObject * object);
+static void gst_ringbuffer_finalize (GObject * object);
+
+static GstObjectClass *parent_class = NULL;
+
+/* ringbuffer abstract base class */
+GType
+gst_ringbuffer_get_type (void)
+{
+ static GType ringbuffer_type = 0;
+
+ if (!ringbuffer_type) {
+ static const GTypeInfo ringbuffer_info = {
+ sizeof (GstRingBufferClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gst_ringbuffer_class_init,
+ NULL,
+ NULL,
+ sizeof (GstRingBuffer),
+ 0,
+ (GInstanceInitFunc) gst_ringbuffer_init,
+ NULL
+ };
+
+ ringbuffer_type = g_type_register_static (GST_TYPE_OBJECT, "GstRingBuffer",
+ &ringbuffer_info, G_TYPE_FLAG_ABSTRACT);
+ }
+ return ringbuffer_type;
+}
+
+static void
+gst_ringbuffer_class_init (GstRingBufferClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstObjectClass *gstobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstobject_class = (GstObjectClass *) klass;
+
+ parent_class = g_type_class_ref (GST_TYPE_OBJECT);
+
+ gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ringbuffer_dispose);
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ringbuffer_finalize);
+}
+
+static void
+gst_ringbuffer_init (GstRingBuffer * ringbuffer)
+{
+ ringbuffer->acquired = FALSE;
+ ringbuffer->state = GST_RINGBUFFER_STATE_STOPPED;
+ ringbuffer->playseg = 0;
+ ringbuffer->writeseg = 1;
+ ringbuffer->segfilled = 0;
+ ringbuffer->waiters = FALSE;
+ ringbuffer->cond = g_cond_new ();
+}
+
+static void
+gst_ringbuffer_dispose (GObject * object)
+{
+ GstRingBuffer *ringbuffer = GST_RINGBUFFER (object);
+
+ G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (ringbuffer));
+}
+
+static void
+gst_ringbuffer_finalize (GObject * object)
+{
+ GstRingBuffer *ringbuffer = GST_RINGBUFFER (object);
+
+ g_cond_free (ringbuffer->cond);
+
+ G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (ringbuffer));
+}
+
+void
+gst_ringbuffer_set_callback (GstRingBuffer * buf, GstRingBufferCallback cb,
+ gpointer data)
+{
+ GST_LOCK (buf);
+ buf->callback = cb;
+ buf->cb_data = data;
+ GST_UNLOCK (buf);
+}
+
+
+gboolean
+gst_ringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
+{
+ gboolean res = FALSE;
+ GstRingBufferClass *rclass;
+
+ GST_LOCK (buf);
+ if (buf->acquired) {
+ res = TRUE;
+ goto done;
+ }
+ buf->acquired = TRUE;
+ GST_UNLOCK (buf);
+
+ rclass = GST_RINGBUFFER_GET_CLASS (buf);
+ if (rclass->acquire)
+ res = rclass->acquire (buf, spec);
+
+ GST_LOCK (buf);
+ if (!res) {
+ buf->acquired = FALSE;
+ }
+done:
+ GST_UNLOCK (buf);
+
+ return res;
+}
+
+gboolean
+gst_ringbuffer_release (GstRingBuffer * buf)
+{
+ gboolean res = FALSE;
+ GstRingBufferClass *rclass;
+
+ GST_LOCK (buf);
+ if (!buf->acquired) {
+ res = TRUE;
+ goto done;
+ }
+ buf->acquired = FALSE;
+ GST_UNLOCK (buf);
+
+ rclass = GST_RINGBUFFER_GET_CLASS (buf);
+ if (rclass->release)
+ res = rclass->release (buf);
+
+ GST_LOCK (buf);
+ if (!res) {
+ buf->acquired = TRUE;
+ }
+done:
+ GST_UNLOCK (buf);
+
+ return res;
+}
+
+gboolean
+gst_ringbuffer_play (GstRingBuffer * buf)
+{
+ gboolean res = FALSE;
+ GstRingBufferClass *rclass;
+
+ GST_LOCK (buf);
+ if (buf->state == GST_RINGBUFFER_STATE_PLAYING) {
+ res = TRUE;
+ goto done;
+ }
+ buf->state = GST_RINGBUFFER_STATE_PLAYING;
+
+ rclass = GST_RINGBUFFER_GET_CLASS (buf);
+ if (rclass->play)
+ res = rclass->play (buf);
+
+ if (!res) {
+ buf->state = GST_RINGBUFFER_STATE_STOPPED;
+ }
+done:
+ GST_UNLOCK (buf);
+
+ return res;
+}
+
+gboolean
+gst_ringbuffer_stop (GstRingBuffer * buf)
+{
+ gboolean res = FALSE;
+ GstRingBufferClass *rclass;
+
+ GST_LOCK (buf);
+ if (buf->state == GST_RINGBUFFER_STATE_STOPPED) {
+ res = TRUE;
+ goto done;
+ }
+ buf->state = GST_RINGBUFFER_STATE_STOPPED;
+
+ rclass = GST_RINGBUFFER_GET_CLASS (buf);
+ if (rclass->stop)
+ res = rclass->stop (buf);
+
+ if (!res) {
+ buf->state = GST_RINGBUFFER_STATE_PLAYING;
+ }
+done:
+ GST_UNLOCK (buf);
+
+ return res;
+}
+
+void
+gst_ringbuffer_callback (GstRingBuffer * buf, guint advance)
+{
+ GST_LOCK (buf);
+ buf->playseg = (buf->playseg + advance) % buf->spec.segtotal;
+ if (buf->playseg == buf->writeseg) {
+ g_print ("underrun!! read %d, write %d\n", buf->playseg, buf->writeseg);
+ buf->writeseg = (buf->playseg + 1) % buf->spec.segtotal;
+ buf->segfilled = 0;
+ }
+ if (buf->waiters)
+ GST_RINGBUFFER_SIGNAL (buf);
+ GST_UNLOCK (buf);
+
+ if (buf->callback)
+ buf->callback (buf, advance, buf->cb_data);
+}
+
+guint
+gst_ringbuffer_write (GstRingBuffer * buf, GstClockTime time, guchar * data,
+ guint len)
+{
+ guint towrite = len;
+ guint written = 0;
+
+ GST_LOCK (buf);
+ /* we write the complete buffer */
+ while (towrite > 0) {
+ guint segavail;
+ guint segwrite;
+
+ /* we cannot write anymore since the buffer is filled, wait for
+ * some space to become available */
+ while (buf->writeseg == buf->playseg) {
+ buf->waiters = TRUE;
+ GST_RINGBUFFER_WAIT (buf);
+ buf->waiters = FALSE;
+ }
+
+ /* this is the available size now in the current segment */
+ segavail = buf->spec.segsize - buf->segfilled;
+
+ /* we write up to the available space */
+ segwrite = MIN (segavail, towrite);
+ memcpy (GST_BUFFER_DATA (buf->data) + buf->writeseg * buf->spec.segsize +
+ buf->segfilled, data, segwrite);
+ towrite -= segwrite;
+ data += segwrite;
+ buf->segfilled += segwrite;
+ written += segwrite;
+ /* we wrote a complete segment, advance the write pointer */
+ if (buf->segfilled == buf->spec.segsize) {
+ buf->writeseg = (buf->writeseg + 1) % buf->spec.segtotal;
+ buf->segfilled = 0;
+ }
+ }
+ GST_UNLOCK (buf);
+
+ return written;
+}
diff --git a/gst-libs/gst/audio/gstringbuffer.h b/gst-libs/gst/audio/gstringbuffer.h
new file mode 100644
index 00000000..aaa37945
--- /dev/null
+++ b/gst-libs/gst/audio/gstringbuffer.h
@@ -0,0 +1,114 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstrinbuffer.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_RINGBUFFER_H__
+#define __GST_RINGBUFFER_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_RINGBUFFER (gst_ringbuffer_get_type())
+#define GST_RINGBUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RINGBUFFER,GstRingBuffer))
+#define GST_RINGBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RINGBUFFER,GstRingBufferClass))
+#define GST_RINGBUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RINGBUFFER, GstRingBufferClass))
+#define GST_IS_RINGBUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RINGBUFFER))
+#define GST_IS_RINGBUFFER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RINGBUFFER))
+
+typedef struct _GstRingBuffer GstRingBuffer;
+typedef struct _GstRingBufferClass GstRingBufferClass;
+typedef struct _GstRingBufferSpec GstRingBufferSpec;
+
+typedef void (*GstRingBufferCallback) (GstRingBuffer *rbuf, guint advance, gpointer data);
+
+typedef enum {
+ GST_RINGBUFFER_STATE_STOPPED,
+ GST_RINGBUFFER_STATE_PLAYING,
+} GstRingBufferState;
+
+typedef enum {
+ GST_SEGSTATE_INVALID,
+ GST_SEGSTATE_EMPTY,
+ GST_SEGSTATE_FILLED,
+} GstRingBufferSegState;
+
+struct _GstRingBufferSpec
+{
+ GstCaps *caps;
+
+ guint segsize;
+ guint segtotal;
+};
+#define GST_RINGBUFFER_GET_COND(buf) (((GstRingBuffer *)buf)->cond)
+#define GST_RINGBUFFER_WAIT(buf) (g_cond_wait (GST_RINGBUFFER_GET_COND (buf), GST_GET_LOCK (buf)))
+#define GST_RINGBUFFER_SIGNAL(buf) (g_cond_signal (GST_RINGBUFFER_GET_COND (buf)))
+
+struct _GstRingBuffer {
+ GstObject object;
+
+ /*< public >*/ /* with LOCK */
+ GCond *cond;
+ gboolean acquired;
+ GstRingBufferState state;
+ GstBuffer *data;
+ GstRingBufferSpec spec;
+ GstRingBufferSegState *segstate;
+
+ gboolean waiters;
+ gint playseg;
+ gint writeseg;
+ gint segfilled;
+
+ GstRingBufferCallback callback;
+ gpointer cb_data;
+};
+
+struct _GstRingBufferClass {
+ GstObjectClass parent_class;
+
+ /*< public >*/
+ gboolean (*acquire) (GstRingBuffer *buf, GstRingBufferSpec *spec);
+ gboolean (*release) (GstRingBuffer *buf);
+
+ gboolean (*play) (GstRingBuffer *buf);
+ gboolean (*stop) (GstRingBuffer *buf);
+};
+
+GType gst_ringbuffer_get_type(void);
+
+void gst_ringbuffer_set_callback (GstRingBuffer *buf, GstRingBufferCallback cb,
+ gpointer data);
+
+gboolean gst_ringbuffer_acquire (GstRingBuffer *buf, GstRingBufferSpec *spec);
+gboolean gst_ringbuffer_release (GstRingBuffer *buf);
+
+gboolean gst_ringbuffer_play (GstRingBuffer *buf);
+gboolean gst_ringbuffer_stop (GstRingBuffer *buf);
+
+guint gst_ringbuffer_write (GstRingBuffer *buf, GstClockTime time,
+ guchar *data, guint len);
+
+void gst_ringbuffer_callback (GstRingBuffer *buf, guint advance);
+
+G_END_DECLS
+
+#endif /* __GST_RINGBUFFER_H__ */
diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am
index 7a163773..3db87f06 100644
--- a/gst-libs/gst/video/Makefile.am
+++ b/gst-libs/gst/video/Makefile.am
@@ -9,4 +9,4 @@ libgstvideoinclude_HEADERS = video.h videosink.h
libgstvideo_la_LIBADD =
libgstvideo_la_CFLAGS = $(GST_CFLAGS)
-libgstvideo_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstvideo_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) ../../../../gstreamer2/gst/base/libgstbase.la
diff --git a/gst-libs/gst/video/gstvideosink.c b/gst-libs/gst/video/gstvideosink.c
index 1085ace9..2d06b315 100644
--- a/gst-libs/gst/video/gstvideosink.c
+++ b/gst-libs/gst/video/gstvideosink.c
@@ -27,17 +27,6 @@
static GstElementClass *parent_class = NULL;
-/* Private methods */
-
-static void
-gst_videosink_set_clock (GstElement * element, GstClock * clock)
-{
- GstVideoSink *videosink;
-
- videosink = GST_VIDEOSINK (element);
-
- videosink->clock = clock;
-}
/* Initing stuff */
@@ -46,7 +35,6 @@ gst_videosink_init (GstVideoSink * videosink)
{
videosink->width = 0;
videosink->height = 0;
- videosink->clock = NULL;
}
static void
@@ -59,8 +47,6 @@ gst_videosink_class_init (GstVideoSinkClass * klass)
gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
-
- gstelement_class->set_clock = gst_videosink_set_clock;
}
/* Public methods */
@@ -83,7 +69,7 @@ gst_videosink_get_type (void)
(GInstanceInitFunc) gst_videosink_init,
};
- videosink_type = g_type_register_static (GST_TYPE_ELEMENT,
+ videosink_type = g_type_register_static (GST_TYPE_BASESINK,
"GstVideoSink", &videosink_info, 0);
}
diff --git a/gst-libs/gst/video/videosink.h b/gst-libs/gst/video/videosink.h
index d1e3aa97..dc7b2805 100644
--- a/gst-libs/gst/video/videosink.h
+++ b/gst-libs/gst/video/videosink.h
@@ -23,6 +23,7 @@
#define __GST_VIDEOSINK_H__
#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
#ifdef __cplusplus
extern "C" {
@@ -40,28 +41,24 @@ extern "C" {
#define GST_VIDEOSINK_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VIDEOSINK, GstVideoSinkClass))
-#define GST_VIDEOSINK_PAD(obj) (GST_VIDEOSINK (obj)->sinkpad)
+#define GST_VIDEOSINK_PAD GST_BASESINK_PAD
+#define GST_VIDEOSINK_CLOCK GST_BASESINK_CLOCK
#define GST_VIDEOSINK_WIDTH(obj) (GST_VIDEOSINK (obj)->width)
#define GST_VIDEOSINK_HEIGHT(obj) (GST_VIDEOSINK (obj)->height)
-#define GST_VIDEOSINK_CLOCK(obj) (GST_VIDEOSINK (obj)->clock)
typedef struct _GstVideoSink GstVideoSink;
typedef struct _GstVideoSinkClass GstVideoSinkClass;
struct _GstVideoSink {
- GstElement element;
-
- GstPad *sinkpad;
+ GstBaseSink element;
gint width, height;
- GstClock *clock;
-
gpointer _gst_reserved[GST_PADDING];
};
struct _GstVideoSinkClass {
- GstElementClass parent_class;
+ GstBaseSinkClass parent_class;
gpointer _gst_reserved[GST_PADDING];
};