summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2010-12-16 15:15:49 +0100
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2010-12-16 15:16:54 +0100
commit53b9f87436c583a9d33c9944511760da2065b5b8 (patch)
tree2823a1e7b4408e051137e2663f69740394a621f2
parent76ad0ee09bf6afbc219067abd3be5c7dd1b31dd6 (diff)
pulsesink: flush remaining buffered samples on EOS
... which can make a difference between all or nothing when dealing with short streams and relatively large ringbuffer segment.
-rw-r--r--ext/pulse/pulsesink.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index 2a9a108b2..796c7b723 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -1649,6 +1649,50 @@ write_failed:
}
}
+/* write pending local samples, must be called with the mainloop lock */
+static void
+gst_pulsering_flush (GstPulseRingBuffer * pbuf)
+{
+#ifdef HAVE_PULSE_0_9_16
+ GstPulseSink *psink;
+
+ psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
+ GST_DEBUG_OBJECT (psink, "entering flush");
+
+ /* flush the buffer if possible */
+ if (pbuf->stream && (pbuf->m_data != NULL) && (pbuf->m_towrite > 0)) {
+#ifndef GST_DISABLE_GST_DEBUG
+ gint bps;
+
+ bps = (GST_RING_BUFFER_CAST (pbuf))->spec.bytes_per_sample;
+ GST_LOG_OBJECT (psink,
+ "flushing %u samples at offset %" G_GINT64_FORMAT,
+ (guint) pbuf->m_towrite / bps, pbuf->m_offset);
+#endif
+
+ if (pa_stream_write (pbuf->stream, (uint8_t *) pbuf->m_data,
+ pbuf->m_towrite, NULL, pbuf->m_offset, PA_SEEK_ABSOLUTE) < 0) {
+ goto write_failed;
+ }
+
+ pbuf->m_towrite = 0;
+ pbuf->m_offset += pbuf->m_towrite; /* keep track of current offset */
+ }
+
+done:
+ return;
+
+ /* ERRORS */
+write_failed:
+ {
+ GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
+ ("pa_stream_write() failed: %s",
+ pa_strerror (pa_context_errno (pbuf->context))), (NULL));
+ goto done;
+ }
+#endif
+}
+
static void gst_pulsesink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_pulsesink_get_property (GObject * object, guint prop_id,
@@ -2579,6 +2623,34 @@ update_failed:
}
#endif
+static void
+gst_pulsesink_flush_ringbuffer (GstPulseSink * psink)
+{
+ GstPulseRingBuffer *pbuf;
+
+ pa_threaded_mainloop_lock (mainloop);
+
+ pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
+
+ if (pbuf == NULL || pbuf->stream == NULL)
+ goto no_buffer;
+
+ gst_pulsering_flush (pbuf);
+
+ /* We're not interested if this operation failed or not */
+unlock:
+ pa_threaded_mainloop_unlock (mainloop);
+
+ return;
+
+ /* ERRORS */
+no_buffer:
+ {
+ GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
+ goto unlock;
+ }
+}
+
static gboolean
gst_pulsesink_event (GstBaseSink * sink, GstEvent * event)
{
@@ -2626,6 +2698,9 @@ gst_pulsesink_event (GstBaseSink * sink, GstEvent * event)
break;
}
+ case GST_EVENT_EOS:
+ gst_pulsesink_flush_ringbuffer (pulsesink);
+ break;
default:
;
}