--- a/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.c Wed Mar 31 22:03:18 2010 +0300
+++ b/gst_plugins_base/gst-libs/gst/audio/gstaudiosink.c Tue Aug 31 15:30:33 2010 +0300
@@ -71,10 +71,6 @@
#include "gstaudiosink.h"
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-
GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug);
#define GST_CAT_DEFAULT gst_audio_sink_debug
@@ -133,6 +129,8 @@
static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf);
static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
+static gboolean gst_audioringbuffer_activate (GstRingBuffer * buf,
+ gboolean active);
/* ringbuffer abstract base class */
static GType
@@ -191,6 +189,8 @@
gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
+ gstringbuffer_class->activate =
+ GST_DEBUG_FUNCPTR (gst_audioringbuffer_activate);
}
typedef guint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
@@ -207,36 +207,55 @@
GstAudioSinkClass *csink;
GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER_CAST (buf);
WriteFunc writefunc;
+ GstMessage *message;
+ GValue val = { 0 };
sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
csink = GST_AUDIO_SINK_GET_CLASS (sink);
GST_DEBUG_OBJECT (sink, "enter thread");
+ GST_OBJECT_LOCK (abuf);
+ GST_DEBUG_OBJECT (sink, "signal wait");
+ GST_AUDIORING_BUFFER_SIGNAL (buf);
+ GST_OBJECT_UNLOCK (abuf);
+
writefunc = csink->write;
if (writefunc == NULL)
goto no_function;
+ g_value_init (&val, G_TYPE_POINTER);
+ g_value_set_pointer (&val, sink->thread);
+ message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
+ GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink));
+ gst_message_set_stream_status_object (message, &val);
+ GST_DEBUG_OBJECT (sink, "posting ENTER stream status");
+ gst_element_post_message (GST_ELEMENT_CAST (sink), message);
+
while (TRUE) {
gint left, len;
guint8 *readptr;
gint readseg;
+ /* buffer must be started */
if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
- gint written = 0;
+ gint written;
left = len;
do {
- written = writefunc (sink, readptr + written, left);
+ written = writefunc (sink, readptr, left);
GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d",
written, left, readseg);
if (written < 0 || written > left) {
+ /* might not be critical, it e.g. happens when aborting playback */
GST_WARNING_OBJECT (sink,
- "error writing data (reason: %s), skipping segment",
- g_strerror (errno));
+ "error writing data in %s (reason: %s), skipping segment (left: %d, written: %d)",
+ GST_DEBUG_FUNCPTR_NAME (writefunc),
+ (errno > 1 ? g_strerror (errno) : "unknown"), left, written);
break;
}
left -= written;
+ readptr += written;
} while (left > 0);
/* clear written samples */
@@ -259,8 +278,9 @@
GST_OBJECT_UNLOCK (abuf);
}
}
- GST_DEBUG_OBJECT (sink, "exit thread");
+ /* Will never be reached */
+ g_assert_not_reached ();
return;
/* ERROR */
@@ -273,6 +293,11 @@
{
GST_OBJECT_UNLOCK (abuf);
GST_DEBUG_OBJECT (sink, "stop running, exit thread");
+ message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
+ GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (sink));
+ gst_message_set_stream_status_object (message, &val);
+ GST_DEBUG_OBJECT (sink, "posting LEAVE stream status");
+ gst_element_post_message (GST_ELEMENT_CAST (sink), message);
return;
}
}
@@ -358,7 +383,6 @@
{
GstAudioSink *sink;
GstAudioSinkClass *csink;
- GstAudioRingBuffer *abuf;
gboolean result = FALSE;
sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
@@ -366,26 +390,18 @@
if (csink->prepare)
result = csink->prepare (sink, spec);
-
if (!result)
goto could_not_prepare;
- /* allocate one more segment as we need some headroom */
- spec->segtotal++;
+ /* set latency to one more segment as we need some headroom */
+ spec->seglatency = spec->segtotal + 1;
buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
- abuf = GST_AUDIORING_BUFFER_CAST (buf);
- abuf->running = TRUE;
+ return TRUE;
- sink->thread =
- g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
- NULL);
- GST_AUDIORING_BUFFER_WAIT (buf);
-
- return result;
-
+ /* ERRORS */
could_not_prepare:
{
GST_DEBUG_OBJECT (sink, "could not prepare device");
@@ -393,6 +409,55 @@
}
}
+static gboolean
+gst_audioringbuffer_activate (GstRingBuffer * buf, gboolean active)
+{
+ GstAudioSink *sink;
+ GstAudioRingBuffer *abuf;
+ GError *error = NULL;
+
+ sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
+ abuf = GST_AUDIORING_BUFFER_CAST (buf);
+
+ if (active) {
+ abuf->running = TRUE;
+
+ GST_DEBUG_OBJECT (sink, "starting thread");
+ sink->thread =
+ g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
+ &error);
+ if (!sink->thread || error != NULL)
+ goto thread_failed;
+
+ GST_DEBUG_OBJECT (sink, "waiting for thread");
+ /* the object lock is taken */
+ GST_AUDIORING_BUFFER_WAIT (buf);
+ GST_DEBUG_OBJECT (sink, "thread is started");
+ } else {
+ abuf->running = FALSE;
+ GST_DEBUG_OBJECT (sink, "signal wait");
+ GST_AUDIORING_BUFFER_SIGNAL (buf);
+
+ GST_OBJECT_UNLOCK (buf);
+
+ /* join the thread */
+ g_thread_join (sink->thread);
+
+ GST_OBJECT_LOCK (buf);
+ }
+ return TRUE;
+
+ /* ERRORS */
+thread_failed:
+ {
+ if (error)
+ GST_ERROR_OBJECT (sink, "could not create thread %s", error->message);
+ else
+ GST_ERROR_OBJECT (sink, "could not create thread for unknown reason");
+ return FALSE;
+ }
+}
+
/* function is called with LOCK */
static gboolean
gst_audioringbuffer_release (GstRingBuffer * buf)
@@ -406,16 +471,6 @@
csink = GST_AUDIO_SINK_GET_CLASS (sink);
abuf = GST_AUDIORING_BUFFER_CAST (buf);
- abuf->running = FALSE;
- GST_DEBUG_OBJECT (sink, "signal wait");
- GST_AUDIORING_BUFFER_SIGNAL (buf);
- GST_OBJECT_UNLOCK (buf);
-
- /* join the thread */
- g_thread_join (sink->thread);
-
- GST_OBJECT_LOCK (buf);
-
/* free the buffer */
gst_buffer_unref (buf->data);
buf->data = NULL;
@@ -426,6 +481,8 @@
if (!result)
goto could_not_unprepare;
+ GST_DEBUG_OBJECT (sink, "unprepared");
+
return result;
could_not_unprepare:
@@ -484,12 +541,13 @@
csink->reset (sink);
GST_DEBUG_OBJECT (sink, "reset done");
}
-
+#if 0
if (abuf->running) {
GST_DEBUG_OBJECT (sink, "stop, waiting...");
GST_AUDIORING_BUFFER_WAIT (buf);
GST_DEBUG_OBJECT (sink, "stopped");
}
+#endif
return TRUE;
}
@@ -551,6 +609,8 @@
gstbaseaudiosink_class->create_ringbuffer =
GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer);
+
+ g_type_class_ref (GST_TYPE_AUDIORING_BUFFER);
}
static void