diff --git a/girs/GstAudio-1.0.gir b/girs/GstAudio-1.0.gir
index 7189f47d1c..0fbffd648c 100644
--- a/girs/GstAudio-1.0.gir
+++ b/girs/GstAudio-1.0.gir
@@ -7893,6 +7893,38 @@ MT safe.
+
+ Gets the current segment base number of the ringbuffer.
+
+MT safe.
+
+
+ Current segment base number of the ringbuffer.
+
+
+
+
+ the #GstAudioRingBuffer to use
+
+
+
+
+
+ Gets the current segment number of the ringbuffer.
+
+MT safe.
+
+
+ Current segment number of the ringbuffer.
+
+
+
+
+ the #GstAudioRingBuffer to use
+
+
+
+
Check if the ringbuffer is acquired and ready to use.
@@ -8234,6 +8266,25 @@ MT safe.
+
+ Sets the current segment number of the ringbuffer.
+
+MT safe.
+
+
+
+
+
+
+ the #GstAudioRingBuffer to use
+
+
+
+ the segment number to set
+
+
+
+
@@ -8363,8 +8414,11 @@ MT safe.
+
+
+
-
+
@@ -8687,6 +8741,9 @@ with a flush or stop.
samples in DSD format (Since: 1.24)
+
+
+
The structure containing the format specification of the ringbuffer.
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c
index 537425da1e..ccb6c15b42 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesink.c
@@ -1199,8 +1199,8 @@ static guint64
gst_audio_base_sink_get_offset (GstAudioBaseSink * sink)
{
guint64 sample, sps;
- gint writeseg, segdone;
- gint diff;
+ guint64 writeseg, segdone;
+ gint64 diff;
/* assume we can append to the previous sample */
sample = sink->next_sample;
@@ -1215,8 +1215,8 @@ gst_audio_base_sink_get_offset (GstAudioBaseSink * sink)
writeseg = sample / sps;
/* get the currently processed segment */
- segdone = g_atomic_int_get (&sink->ringbuffer->segdone)
- - sink->ringbuffer->segbase;
+ segdone = gst_audio_ring_buffer_get_segdone (sink->ringbuffer)
+ - gst_audio_ring_buffer_get_segbase (sink->ringbuffer);
/* see how far away it is from the write segment */
diff = writeseg - segdone;
@@ -1728,7 +1728,8 @@ gst_audio_base_sink_get_alignment (GstAudioBaseSink * sink,
gint64 align;
gint64 sample_diff;
gint64 max_sample_diff;
- gint segdone = g_atomic_int_get (&ringbuf->segdone) - ringbuf->segbase;
+ guint64 segdone = gst_audio_ring_buffer_get_segdone (sink->ringbuffer)
+ - gst_audio_ring_buffer_get_segbase (sink->ringbuffer);
gint64 samples_done = segdone * (gint64) ringbuf->samples_per_seg;
gint64 headroom = sample_offset - samples_done;
gboolean allow_align = TRUE;
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesrc.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesrc.c
index 04916f36fd..4e4d68f54f 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesrc.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiobasesrc.c
@@ -700,8 +700,9 @@ static guint64
gst_audio_base_src_get_offset (GstAudioBaseSrc * src)
{
guint64 sample;
- gint readseg, segdone, segtotal, sps;
- gint diff;
+ guint64 readseg, segdone;
+ gint segtotal, sps;
+ gint64 diff;
/* assume we can append to the previous sample */
sample = src->next_sample;
@@ -710,11 +711,12 @@ gst_audio_base_src_get_offset (GstAudioBaseSrc * src)
segtotal = src->ringbuffer->spec.segtotal;
/* get the currently processed segment */
- segdone = g_atomic_int_get (&src->ringbuffer->segdone)
- - src->ringbuffer->segbase;
+ segdone = gst_audio_ring_buffer_get_segdone (src->ringbuffer)
+ - gst_audio_ring_buffer_get_segbase (src->ringbuffer);
if (sample != -1) {
- GST_DEBUG_OBJECT (src, "at segment %d and sample %" G_GUINT64_FORMAT,
+ GST_DEBUG_OBJECT (src,
+ "at segment %" G_GUINT64_FORMAT " and sample %" G_GUINT64_FORMAT,
segdone, sample);
/* figure out the segment and the offset inside the segment where
* the sample should be read from. */
@@ -725,20 +727,22 @@ gst_audio_base_src_get_offset (GstAudioBaseSrc * src)
* (where we are reading). */
diff = segdone - readseg;
if (diff >= segtotal) {
- GST_DEBUG_OBJECT (src, "dropped, align to segment %d", segdone);
+ GST_DEBUG_OBJECT (src, "dropped, align to segment %" G_GUINT64_FORMAT,
+ segdone);
/* sample would be dropped, position to next playable position */
sample = ((guint64) (segdone)) * sps;
}
} else {
/* no previous sample, go to the current position */
- GST_DEBUG_OBJECT (src, "first sample, align to current %d", segdone);
- sample = ((guint64) (segdone)) * sps;
+ GST_DEBUG_OBJECT (src, "first sample, align to current %" G_GUINT64_FORMAT,
+ segdone);
+ sample = segdone * sps;
readseg = segdone;
}
GST_DEBUG_OBJECT (src,
- "reading from %d, we are at %d, sample %" G_GUINT64_FORMAT, readseg,
- segdone, sample);
+ "reading from %" G_GUINT64_FORMAT ", we are at %" G_GUINT64_FORMAT
+ ", sample %" G_GUINT64_FORMAT, readseg, segdone, sample);
return sample;
}
@@ -876,20 +880,22 @@ gst_audio_base_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
GstClockTime base_time;
GstClockTime current_time;
guint64 running_time_sample;
- gint running_time_segment;
- gint last_read_segment;
- gint segment_skew;
+ guint64 running_time_segment;
+ guint64 last_read_segment;
+ gint64 segment_skew;
gint sps;
- gint segments_written;
- gint last_written_segment;
+ guint64 segments_written;
+ guint64 last_written_segment;
/* get the amount of segments written from the device by now */
- segments_written = g_atomic_int_get (&ringbuffer->segdone);
+ segments_written = gst_audio_ring_buffer_get_segdone (src->ringbuffer);
/* subtract the base to segments_written to get the number of the
* last written segment in the ringbuffer
* (one segment written = segment 0) */
- last_written_segment = segments_written - ringbuffer->segbase - 1;
+ last_written_segment =
+ segments_written - gst_audio_ring_buffer_get_segbase (ringbuffer) -
+ 1;
/* samples per segment */
sps = ringbuffer->samples_per_seg;
@@ -923,13 +929,16 @@ gst_audio_base_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
GST_TIME_FORMAT
"\n timestamp = %"
GST_TIME_FORMAT
- "\n running_time_segment = %d"
- "\n last_written_segment = %d"
- "\n segment_skew (running time segment - last_written_segment) = %d"
- "\n last_read_segment = %d",
- GST_TIME_ARGS (running_time), GST_TIME_ARGS (timestamp),
- running_time_segment, last_written_segment, segment_skew,
- last_read_segment);
+ "\n running_time_segment = %"
+ G_GUINT64_FORMAT
+ "\n last_written_segment = %"
+ G_GUINT64_FORMAT
+ "\n segment_skew (running time segment - last_written_segment) = %"
+ G_GINT64_FORMAT
+ "\n last_read_segment = %"
+ G_GUINT64_FORMAT, GST_TIME_ARGS (running_time),
+ GST_TIME_ARGS (timestamp), running_time_segment,
+ last_written_segment, segment_skew, last_read_segment);
/* Resync the ringbuffer if:
*
@@ -943,8 +952,8 @@ gst_audio_base_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
*/
if ((segment_skew >= ringbuffer->spec.segtotal) ||
(last_read_segment == 0) || first_sample) {
- gint new_read_segment;
- gint segment_diff;
+ guint64 new_read_segment;
+ guint64 segment_diff;
guint64 new_sample;
/* the difference between running_time and the last written segment */
@@ -954,11 +963,11 @@ gst_audio_base_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
gst_audio_ring_buffer_advance (ringbuffer, segment_diff);
/* we move the new read segment to the last known written segment */
- new_read_segment =
- g_atomic_int_get (&ringbuffer->segdone) - ringbuffer->segbase;
+ new_read_segment = gst_audio_ring_buffer_get_segdone (src->ringbuffer)
+ - gst_audio_ring_buffer_get_segbase (src->ringbuffer);
/* we calculate the new sample value */
- new_sample = ((guint64) new_read_segment) * sps;
+ new_sample = new_read_segment * sps;
/* and get the relative time to this -> our new timestamp */
timestamp = gst_util_uint64_scale_int (new_sample, GST_SECOND, rate);
@@ -967,7 +976,7 @@ gst_audio_base_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
src->next_sample = new_sample + samples;
GST_DEBUG_OBJECT (bsrc,
- "Timeshifted the ringbuffer with %d segments: "
+ "Timeshifted the ringbuffer with %" G_GINT64_FORMAT " segments: "
"Updating the timestamp to %" GST_TIME_FORMAT ", "
"and src->next_sample to %" G_GUINT64_FORMAT, segment_diff,
GST_TIME_ARGS (timestamp), src->next_sample);
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.c
index bd08a24738..9781ef28bb 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.c
@@ -46,6 +46,124 @@
GST_DEBUG_CATEGORY_STATIC (gst_audio_ring_buffer_debug);
#define GST_CAT_DEFAULT gst_audio_ring_buffer_debug
+/* TODO: use GLib's once https://gitlab.gnome.org/GNOME/glib/issues/1076 lands, or
+ * use C11 atomics once MS arrives in this century.
+ *
+ * We also assume that signed overflow just wraps around because unfortunately
+ * there are no unsigned versions in MSVC. */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
+#include
+
+static inline guint64
+gst_atomic_uint64_add (guint64 * atomic, guint64 n)
+{
+ return atomic_fetch_add ((_Atomic guint64 *) atomic, n);
+}
+
+static inline void
+gst_atomic_uint64_set (guint64 * atomic, guint64 n)
+{
+ atomic_store ((_Atomic guint64 *) atomic, n);
+}
+
+static inline guint64
+gst_atomic_uint64_get (guint64 * atomic)
+{
+ gint64 ret = atomic_load ((_Atomic guint64 *) atomic);
+ return ret;
+}
+#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
+static inline guint64
+gst_atomic_uint64_add (guint64 * atomic, guint64 n)
+{
+ return __sync_fetch_and_add (atomic, n);
+}
+
+static inline void
+gst_atomic_uint64_set (guint64 * atomic, guint64 n)
+{
+ __sync_synchronize ();
+ __asm__ __volatile__ ("":::"memory");
+ *atomic = n;
+}
+
+static inline guint64
+gst_atomic_uint64_get (guint64 * atomic)
+{
+ gint64 ret = *atomic;
+ __sync_synchronize ();
+ __asm__ __volatile__ ("":::"memory");
+ return ret;
+}
+#elif defined (G_PLATFORM_WIN32)
+#include
+static inline guint64
+gst_atomic_uint64_add (guint64 * atomic, guint64 n)
+{
+ return InterlockedExchangeAdd64 ((gint64 *) atomic, (gint64) n);
+}
+
+static inline void
+gst_atomic_uint64_set (guint64 * atomic, guint64 n)
+{
+ *atomic = n;
+ MemoryBarrier ();
+}
+
+static inline guint64
+gst_atomic_uint64_get (guint64 * atomic)
+{
+ MemoryBarrier ();
+ return *atomic;
+}
+#else
+#define STR_TOKEN(s) #s
+#define STR(s) STR_TOKEN(s)
+#pragma message "No 64-bit atomic int defined for this " STR(TARGET_CPU) " platform/toolchain!"
+
+#define NO_64BIT_ATOMIC_INT_FOR_PLATFORM
+G_LOCK_DEFINE_STATIC (atomic_lock);
+static inline guint64
+gst_atomic_uint64_add (guint64 * atomic, guint64 n)
+{
+ guint64 ret;
+
+ G_LOCK (atomic_lock);
+ *atomic += n;
+ ret = *atomic;
+ G_UNLOCK (atomic_lock);
+
+ return ret;
+}
+
+static inline void
+gst_atomic_uint64_set (guint64 * atomic, guint64 n)
+{
+ G_LOCK (atomic_lock);
+ *atomic = n;
+ G_UNLOCK (atomic_lock);
+}
+
+static inline guint64
+gst_atomic_uint64_get (gint64 * atomic)
+{
+ guint64 ret;
+
+ G_LOCK (atomic_lock);
+ ret = *atomic;
+ G_UNLOCK (atomic_lock);
+
+ return ret;
+}
+#endif
+
+struct _GstAudioRingBufferPrivate
+{
+ /* ATOMIC */
+ guint64 segdone;
+ guint64 segbase;
+};
+
static void gst_audio_ring_buffer_dispose (GObject * object);
static void gst_audio_ring_buffer_finalize (GObject * object);
@@ -55,7 +173,7 @@ static guint default_commit (GstAudioRingBuffer * buf, guint64 * sample,
guint8 * data, gint in_samples, gint out_samples, gint * accum);
/* ringbuffer abstract base class */
-G_DEFINE_ABSTRACT_TYPE (GstAudioRingBuffer, gst_audio_ring_buffer,
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstAudioRingBuffer, gst_audio_ring_buffer,
GST_TYPE_OBJECT);
static void
@@ -80,6 +198,7 @@ gst_audio_ring_buffer_class_init (GstAudioRingBufferClass * klass)
static void
gst_audio_ring_buffer_init (GstAudioRingBuffer * ringbuffer)
{
+ ringbuffer->priv = gst_audio_ring_buffer_get_instance_private (ringbuffer);
ringbuffer->open = FALSE;
ringbuffer->acquired = FALSE;
g_atomic_int_set (&ringbuffer->state, GST_AUDIO_RING_BUFFER_STATE_STOPPED);
@@ -89,6 +208,8 @@ gst_audio_ring_buffer_init (GstAudioRingBuffer * ringbuffer)
ringbuffer->flushing = TRUE;
ringbuffer->segbase = 0;
ringbuffer->segdone = 0;
+ ringbuffer->priv->segbase = 0;
+ ringbuffer->priv->segdone = 0;
}
static void
@@ -813,7 +934,9 @@ gst_audio_ring_buffer_release (GstAudioRingBuffer * buf)
if (G_UNLIKELY (!res))
goto release_failed;
+ gst_atomic_uint64_set (&buf->priv->segdone, 0);
g_atomic_int_set (&buf->segdone, 0);
+ buf->priv->segbase = 0;
buf->segbase = 0;
g_free (buf->empty_seg);
buf->empty_seg = NULL;
@@ -1348,16 +1471,16 @@ not_acquired:
guint64
gst_audio_ring_buffer_samples_done (GstAudioRingBuffer * buf)
{
- gint segdone;
+ guint64 segdone;
guint64 samples;
g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), 0);
/* get the amount of segments we processed */
- segdone = g_atomic_int_get (&buf->segdone);
+ segdone = gst_atomic_uint64_get (&buf->priv->segdone);
/* convert to samples */
- samples = ((guint64) segdone) * buf->samples_per_seg;
+ samples = segdone * buf->samples_per_seg;
return samples;
}
@@ -1379,6 +1502,8 @@ gst_audio_ring_buffer_samples_done (GstAudioRingBuffer * buf)
void
gst_audio_ring_buffer_set_sample (GstAudioRingBuffer * buf, guint64 sample)
{
+ guint64 segdone;
+
g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
if (sample == -1)
@@ -1390,12 +1515,69 @@ gst_audio_ring_buffer_set_sample (GstAudioRingBuffer * buf, guint64 sample)
/* FIXME, we assume the ringbuffer can restart at a random
* position, round down to the beginning and keep track of
* offset when calculating the processed samples. */
- buf->segbase = buf->segdone - sample / buf->samples_per_seg;
+ segdone = gst_atomic_uint64_get (&buf->priv->segdone);
+ buf->priv->segbase = segdone - sample / buf->samples_per_seg;
+ buf->segbase = buf->priv->segbase;
gst_audio_ring_buffer_clear_all (buf);
- GST_DEBUG_OBJECT (buf, "set sample to %" G_GUINT64_FORMAT ", segbase %d",
- sample, buf->segbase);
+ GST_DEBUG_OBJECT (buf,
+ "set sample to %" G_GUINT64_FORMAT ", segbase %" G_GUINT64_FORMAT, sample,
+ buf->priv->segbase);
+}
+
+/**
+ * gst_audio_ring_buffer_set_segdone:
+ * @buf: the #GstAudioRingBuffer to use
+ * @segdone: the segment number to set
+ *
+ * Sets the current segment number of the ringbuffer.
+ *
+ * MT safe.
+ *
+ * Since: 1.26
+ */
+void
+gst_audio_ring_buffer_set_segdone (GstAudioRingBuffer * buf, guint64 segdone)
+{
+ gst_atomic_uint64_set (&buf->priv->segdone, segdone);
+ g_atomic_int_set (&buf->segdone, segdone);
+}
+
+/**
+ * gst_audio_ring_buffer_get_segdone:
+ * @buf: the #GstAudioRingBuffer to use
+ *
+ * Gets the current segment number of the ringbuffer.
+ *
+ * MT safe.
+ *
+ * Returns: Current segment number of the ringbuffer.
+ *
+ * Since: 1.26
+ */
+guint64
+gst_audio_ring_buffer_get_segdone (GstAudioRingBuffer * buf)
+{
+ return gst_atomic_uint64_get (&buf->priv->segdone);
+}
+
+/**
+ * gst_audio_ring_buffer_get_segbase:
+ * @buf: the #GstAudioRingBuffer to use
+ *
+ * Gets the current segment base number of the ringbuffer.
+ *
+ * MT safe.
+ *
+ * Returns: Current segment base number of the ringbuffer.
+ *
+ * Since: 1.26
+ */
+guint64
+gst_audio_ring_buffer_get_segbase (GstAudioRingBuffer * buf)
+{
+ return gst_atomic_uint64_get (&buf->priv->segbase);
}
/**
@@ -1445,7 +1627,7 @@ gst_audio_ring_buffer_clear_all (GstAudioRingBuffer * buf)
static gboolean
wait_segment (GstAudioRingBuffer * buf)
{
- gint segments;
+ guint64 segments;
gboolean wait = TRUE;
/* buffer must be started now or we deadlock since nobody is reading */
@@ -1456,12 +1638,12 @@ wait_segment (GstAudioRingBuffer * buf)
goto no_start;
GST_DEBUG_OBJECT (buf, "start!");
- segments = g_atomic_int_get (&buf->segdone);
+ segments = gst_atomic_uint64_get (&buf->priv->segdone);
gst_audio_ring_buffer_start (buf);
/* After starting, the writer may have wrote segments already and then we
* don't need to wait anymore */
- if (G_LIKELY (g_atomic_int_get (&buf->segdone) != segments))
+ if (G_LIKELY (gst_atomic_uint64_get (&buf->priv->segdone) != segments))
wait = FALSE;
}
@@ -1625,10 +1807,10 @@ static guint
default_commit (GstAudioRingBuffer * buf, guint64 * sample,
guint8 * data, gint in_samples, gint out_samples, gint * accum)
{
- gint segdone;
+ guint64 segdone;
gint segsize, segtotal, channels, bps, bpf, sps;
guint8 *dest, *data_end;
- gint writeseg, sampleoff;
+ guint64 writeseg, sampleoff;
gint *toprocess;
gint inr, outr;
gboolean reverse;
@@ -1677,17 +1859,20 @@ default_commit (GstAudioRingBuffer * buf, guint64 * sample,
gboolean skip;
while (TRUE) {
- gint diff;
+ gint64 diff;
/* get the currently processed segment */
- segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
+ segdone =
+ gst_atomic_uint64_get (&buf->priv->segdone) - buf->priv->segbase;
/* see how far away it is from the write segment */
diff = writeseg - segdone;
GST_DEBUG_OBJECT (buf,
- "pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d, base %d",
- segdone, writeseg, sampleoff, diff, segtotal, segsize, buf->segbase);
+ "pointer at %" G_GUINT64_FORMAT ", write to %" G_GUINT64_FORMAT "-%"
+ G_GUINT64_FORMAT ", diff %" G_GINT64_FORMAT
+ ", segtotal %d, segsize %d, base %" G_GUINT64_FORMAT, segdone,
+ writeseg, sampleoff, diff, segtotal, segsize, buf->priv->segbase);
/* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */
if (G_UNLIKELY (diff < 0)) {
@@ -1716,7 +1901,8 @@ default_commit (GstAudioRingBuffer * buf, guint64 * sample,
d_end = d + avail;
*sample += avail / bpf;
- GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
+ GST_DEBUG_OBJECT (buf,
+ "write @%p seg %d, sps %d, off %" G_GUINT64_FORMAT ", avail %d",
dest + ws * segsize, ws, sps, sampleoff, avail);
if (need_reorder) {
@@ -1859,8 +2045,8 @@ guint
gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
guint8 * data, guint len, GstClockTime * timestamp)
{
- gint segdone;
- gint segsize, segtotal, channels, bps, bpf, sps, readseg = 0;
+ guint64 segdone, readseg = 0;
+ gint segsize, segtotal, channels, bps, bpf, sps;
guint8 *dest;
guint to_read;
gboolean need_reorder;
@@ -1890,10 +2076,11 @@ gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
sampleoff = (sample % sps);
while (TRUE) {
- gint diff;
+ gint64 diff;
/* get the currently processed segment */
- segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
+ segdone =
+ gst_atomic_uint64_get (&buf->priv->segdone) - buf->priv->segbase;
/* see how far away it is from the read segment, normally segdone (where
* the hardware is writing) is bigger than readseg (where software is
@@ -1901,10 +2088,10 @@ gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
diff = segdone - readseg;
GST_DEBUG_OBJECT
- (buf, "pointer at %d, sample %" G_GUINT64_FORMAT
- ", read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d",
- segdone, sample, readseg, sampleoff, to_read, diff, segtotal,
- segsize);
+ (buf, "pointer at %" G_GUINT64_FORMAT ", sample %" G_GUINT64_FORMAT
+ ", read from %" G_GUINT64_FORMAT "-%d, to_read %d, diff %"
+ G_GINT64_FORMAT ", segtotal %d, segsize %d", segdone, sample, readseg,
+ sampleoff, to_read, diff, segtotal, segsize);
/* segment too far ahead, reader too slow */
if (G_UNLIKELY (diff >= segtotal)) {
@@ -1928,7 +2115,8 @@ gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
readseg = readseg % segtotal;
sampleslen = MIN (sps - sampleoff, to_read);
- GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
+ GST_DEBUG_OBJECT (buf,
+ "read @%p seg %" G_GUINT64_FORMAT ", off %d, sampleslen %d",
dest + readseg * segsize, readseg, sampleoff, sampleslen);
if (need_reorder) {
@@ -1957,7 +2145,8 @@ gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
if (buf->timestamps && timestamp) {
*timestamp = buf->timestamps[readseg % segtotal];
GST_DEBUG_OBJECT (buf, "Retrieved timestamp %" GST_TIME_FORMAT
- " @ %d", GST_TIME_ARGS (*timestamp), readseg % segtotal);
+ " @ %" G_GUINT64_FORMAT, GST_TIME_ARGS (*timestamp),
+ readseg % segtotal);
}
return len - to_read;
@@ -1990,7 +2179,7 @@ gst_audio_ring_buffer_prepare_read (GstAudioRingBuffer * buf, gint * segment,
guint8 ** readptr, gint * len)
{
guint8 *data;
- gint segdone;
+ guint64 segdone;
g_return_val_if_fail (GST_IS_AUDIO_RING_BUFFER (buf), FALSE);
@@ -2008,14 +2197,15 @@ gst_audio_ring_buffer_prepare_read (GstAudioRingBuffer * buf, gint * segment,
data = buf->memory;
/* get the position of the pointer */
- segdone = g_atomic_int_get (&buf->segdone);
+ segdone = gst_atomic_uint64_get (&buf->priv->segdone);
*segment = segdone % buf->spec.segtotal;
*len = buf->spec.segsize;
*readptr = data + *segment * *len;
- GST_LOG_OBJECT (buf, "prepare read from segment %d (real %d) @%p",
- *segment, segdone, *readptr);
+ GST_LOG_OBJECT (buf,
+ "prepare read from segment %d (real %" G_GUINT64_FORMAT ") @%p", *segment,
+ segdone, *readptr);
/* callback to fill the memory with data, for pull based
* scheduling. */
@@ -2041,6 +2231,7 @@ gst_audio_ring_buffer_advance (GstAudioRingBuffer * buf, guint advance)
g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
/* update counter */
+ gst_atomic_uint64_add (&buf->priv->segdone, advance);
g_atomic_int_add (&buf->segdone, advance);
/* the lock is already taken when the waiting flag is set,
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.h b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.h
index e188636145..3f9db5b84a 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.h
+++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioringbuffer.h
@@ -42,6 +42,7 @@ G_BEGIN_DECLS
typedef struct _GstAudioRingBuffer GstAudioRingBuffer;
typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass;
typedef struct _GstAudioRingBufferSpec GstAudioRingBufferSpec;
+typedef struct _GstAudioRingBufferPrivate GstAudioRingBufferPrivate;
/**
* GstAudioRingBufferCallback:
@@ -241,7 +242,8 @@ struct _GstAudioRingBuffer {
GDestroyNotify cb_data_notify;
/*< private >*/
- gpointer _gst_reserved[GST_PADDING - 1];
+ GstAudioRingBufferPrivate *priv;
+ gpointer _gst_reserved[GST_PADDING - 2];
};
/**
@@ -435,6 +437,15 @@ void gst_audio_ring_buffer_advance (GstAudioRingBuffer *buf,
GST_AUDIO_API
void gst_audio_ring_buffer_may_start (GstAudioRingBuffer *buf, gboolean allowed);
+GST_AUDIO_API
+void gst_audio_ring_buffer_set_segdone (GstAudioRingBuffer *buf, guint64 segdone);
+
+GST_AUDIO_API
+guint64 gst_audio_ring_buffer_get_segdone (GstAudioRingBuffer *buf);
+
+GST_AUDIO_API
+guint64 gst_audio_ring_buffer_get_segbase (GstAudioRingBuffer *buf);
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAudioRingBuffer, gst_object_unref)
G_END_DECLS
diff --git a/subprojects/gst-plugins-good/ext/pulse/pulsesink.c b/subprojects/gst-plugins-good/ext/pulse/pulsesink.c
index a4b86de489..a141e8018a 100644
--- a/subprojects/gst-plugins-good/ext/pulse/pulsesink.c
+++ b/subprojects/gst-plugins-good/ext/pulse/pulsesink.c
@@ -744,8 +744,8 @@ gst_pulsering_stream_latency_cb (pa_stream * s, void *userdata)
* less. One concern here is that latency updates happen every 100ms, which
* means segdone is not updated very often, but increasing the update
* frequency would mean more communication overhead. */
- g_atomic_int_set (&ringbuf->segdone,
- (int) gst_util_uint64_scale_ceil (info->read_index, 1,
+ gst_audio_ring_buffer_set_segdone (ringbuf,
+ gst_util_uint64_scale_ceil (info->read_index, 1,
ringbuf->spec.segsize));
}