Merge branch 'audioringbuffer-segdone-overflow' into 'main'

audioringbuffer: Avoid overflows of segment done counter

See merge request gstreamer/gstreamer!6740
This commit is contained in:
Sebastian Dröge 2024-05-04 00:01:00 +00:00
commit c9c6e19dee
5 changed files with 261 additions and 69 deletions

View file

@ -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;

View file

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

View file

@ -46,6 +46,104 @@
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(__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 <windows.h>
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 +153,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 +178,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 +188,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 +914,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 +1451,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 +1482,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 +1495,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 +1607,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 +1618,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 +1787,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 +1839,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 +1881,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 +2025,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 +2056,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 +2068,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 +2095,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 +2125,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 +2159,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 +2177,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 +2211,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,

View file

@ -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

View file

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