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)); }