gst-libs/gst/audio/: Add flushing mode to the ringbuffer so that it in all cases...
authorWim Taymans <wim.taymans@gmail.com>
Mon, 31 Oct 2005 10:30:41 +0000 (10:30 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 31 Oct 2005 10:30:41 +0000 (10:30 +0000)
Original commit message from CVS:
* 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.

ChangeLog
gst-libs/gst/audio/gstbaseaudiosink.c
gst-libs/gst/audio/gstringbuffer.c
gst-libs/gst/audio/gstringbuffer.h

index 6d34cc8..9960cce 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+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),
index 5dbfc94..1bb5f4d 100644 (file)
@@ -297,13 +297,12 @@ gst_base_audio_sink_event (GstBaseSink * bsink, GstEvent * event)
 
   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);
index 1dde58a..cae51f1 100644 (file)
@@ -31,6 +31,8 @@ static void gst_ring_buffer_init (GstRingBuffer * 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 */
@@ -608,6 +610,28 @@ gst_ring_buffer_is_acquired (GstRingBuffer * buf)
   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:
@@ -631,6 +655,9 @@ gst_ring_buffer_start (GstRingBuffer * buf)
   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);
@@ -669,29 +696,22 @@ done:
   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);
@@ -718,9 +738,41 @@ gst_ring_buffer_pause (GstRingBuffer * buf)
   }
 
 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;
+  }
 }
 
 /**
@@ -744,6 +796,9 @@ gst_ring_buffer_stop (GstRingBuffer * buf)
   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);
@@ -772,6 +827,12 @@ done:
   GST_UNLOCK (buf);
 
   return res;
+
+flushing:
+  {
+    GST_UNLOCK (buf);
+    return FALSE;
+  }
 }
 
 /**
@@ -916,12 +977,17 @@ wait_segment (GstRingBuffer * buf)
 
   /* 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;
@@ -937,6 +1003,12 @@ not_started:
     GST_DEBUG ("stopped processing");
     return FALSE;
   }
+flushing:
+  {
+    GST_UNLOCK (buf);
+    GST_DEBUG ("flushing");
+    return FALSE;
+  }
 }
 
 /**
index 955db07..bb03818 100644 (file)
@@ -172,6 +172,8 @@ struct _GstRingBuffer {
   GstRingBufferCallback  callback;
   gpointer               cb_data;
 
+  gboolean              flushing;
+
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };
@@ -224,6 +226,9 @@ gboolean    gst_ring_buffer_release         (GstRingBuffer *buf);
 
 gboolean       gst_ring_buffer_is_acquired     (GstRingBuffer *buf);
 
+/* flushing */
+void           gst_ring_buffer_set_flushing    (GstRingBuffer *buf, gboolean flushing);
+
 /* playback/pause */
 gboolean       gst_ring_buffer_start           (GstRingBuffer *buf);
 gboolean       gst_ring_buffer_pause           (GstRingBuffer *buf);