+2005-10-31 Wim Taymans <wim@fluendo.com>
+
+ * gst-libs/gst/audio/gstbaseaudiosink.c:
+ (gst_base_audio_sink_event), (gst_base_audio_sink_get_offset),
+ (gst_base_audio_sink_render):
+ * gst-libs/gst/audio/gstringbuffer.c:
+ (gst_ring_buffer_open_device), (gst_ring_buffer_close_device),
+ (gst_ring_buffer_set_flushing), (gst_ring_buffer_start),
+ (gst_ring_buffer_pause_unlocked), (gst_ring_buffer_pause),
+ (gst_ring_buffer_stop), (wait_segment), (gst_ring_buffer_commit),
+ (gst_ring_buffer_read):
+ * gst-libs/gst/audio/gstringbuffer.h:
+ Add flushing mode to the ringbuffer so that it in all cases does
+ not try to handle more audio. This makes sure it does not try to
+ block anymore when flushing and fixes a livelock.
+
2005-10-29 Tim-Philipp Müller <tim at centricular dot net>
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_query_convert),
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
- gst_ring_buffer_pause (sink->ringbuffer);
- gst_ring_buffer_clear_all (sink->ringbuffer);
+ gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
break;
case GST_EVENT_FLUSH_STOP:
/* always resync on sample after a flush */
sink->next_sample = -1;
- gst_ring_buffer_clear_all (sink->ringbuffer);
+ gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
break;
case GST_EVENT_EOS:
gst_ring_buffer_start (sink->ringbuffer);
static void gst_ring_buffer_dispose (GObject * object);
static void gst_ring_buffer_finalize (GObject * object);
+static gboolean gst_ring_buffer_pause_unlocked (GstRingBuffer * buf);
+
static GstObjectClass *parent_class = NULL;
/* ringbuffer abstract base class */
return res;
}
+/**
+ * gst_ring_buffer_set_flushing:
+ * @buf: the #GstRingBuffer to flush
+ *
+ * Set the ringbuffer to flushing mode or normal mode.
+ *
+ * MT safe.
+ */
+void
+gst_ring_buffer_set_flushing (GstRingBuffer * buf, gboolean flushing)
+{
+ GST_LOCK (buf);
+ buf->flushing = flushing;
+
+ gst_ring_buffer_clear_all (buf);
+ if (flushing) {
+ gst_ring_buffer_pause_unlocked (buf);
+ }
+
+ GST_UNLOCK (buf);
+}
+
/**
* gst_ring_buffer_start:
GST_DEBUG_OBJECT (buf, "starting ringbuffer");
GST_LOCK (buf);
+ if (buf->flushing)
+ goto flushing;
+
/* if stopped, set to started */
res = g_atomic_int_compare_and_exchange (&buf->state,
GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STARTED);
GST_UNLOCK (buf);
return res;
+
+flushing:
+ {
+ GST_UNLOCK (buf);
+ return FALSE;
+ }
}
-/**
- * gst_ring_buffer_pause:
- * @buf: the #GstRingBuffer to pause
- *
- * Pause processing samples from the ringbuffer.
- *
- * Returns: TRUE if the device could be paused, FALSE on error.
- *
- * MT safe.
- */
-gboolean
-gst_ring_buffer_pause (GstRingBuffer * buf)
+static gboolean
+gst_ring_buffer_pause_unlocked (GstRingBuffer * buf)
{
gboolean res = FALSE;
GstRingBufferClass *rclass;
- g_return_val_if_fail (buf != NULL, FALSE);
-
GST_DEBUG_OBJECT (buf, "pausing ringbuffer");
- GST_LOCK (buf);
/* if started, set to paused */
res = g_atomic_int_compare_and_exchange (&buf->state,
GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_PAUSED);
}
done:
+ return res;
+}
+
+/**
+ * gst_ring_buffer_pause:
+ * @buf: the #GstRingBuffer to pause
+ *
+ * Pause processing samples from the ringbuffer.
+ *
+ * Returns: TRUE if the device could be paused, FALSE on error.
+ *
+ * MT safe.
+ */
+gboolean
+gst_ring_buffer_pause (GstRingBuffer * buf)
+{
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (buf != NULL, FALSE);
+
+ GST_LOCK (buf);
+ if (buf->flushing)
+ goto flushing;
+
+ res = gst_ring_buffer_pause_unlocked (buf);
+
GST_UNLOCK (buf);
return res;
+
+flushing:
+ {
+ GST_UNLOCK (buf);
+ return FALSE;
+ }
}
/**
GST_DEBUG_OBJECT (buf, "stopping");
GST_LOCK (buf);
+ if (buf->flushing)
+ goto flushing;
+
/* if started, set to stopped */
res = g_atomic_int_compare_and_exchange (&buf->state,
GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STOPPED);
GST_UNLOCK (buf);
return res;
+
+flushing:
+ {
+ GST_UNLOCK (buf);
+ return FALSE;
+ }
}
/**
/* take lock first, then update our waiting flag */
GST_LOCK (buf);
+ if (buf->flushing)
+ goto flushing;
+
if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
GST_DEBUG ("waiting..");
if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
goto not_started;
GST_RING_BUFFER_WAIT (buf);
+ if (buf->flushing)
+ goto flushing;
if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
goto not_started;
GST_DEBUG ("stopped processing");
return FALSE;
}
+flushing:
+ {
+ GST_UNLOCK (buf);
+ GST_DEBUG ("flushing");
+ return FALSE;
+ }
}
/**