123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- From 638a01381ea5ba8348138476bc88b338234cd858 Mon Sep 17 00:00:00 2001
- From: osy <osy@turing.llc>
- Date: Mon, 1 Aug 2022 13:20:20 -0700
- Subject: [PATCH] gstaudiobasesrc: reset clock when caps change
- This follows similar code from gstaudiobasesink. When the caps change, we
- need to reset the clock, otherwise a long period of silence will be
- recorded.
- ---
- gst-libs/gst/audio/gstaudiobasesrc.c | 21 +++++++++++++++------
- 1 file changed, 15 insertions(+), 6 deletions(-)
- diff --git a/gst-libs/gst/audio/gstaudiobasesrc.c b/gst-libs/gst/audio/gstaudiobasesrc.c
- index a384e8eb3..6977f11e4 100644
- --- a/gst-libs/gst/audio/gstaudiobasesrc.c
- +++ b/gst-libs/gst/audio/gstaudiobasesrc.c
- @@ -299,6 +299,14 @@ clock_disabled:
- }
- }
-
- +static gboolean
- +gst_audio_base_src_is_self_provided_clock (GstAudioBaseSrc * sink)
- +{
- + return (sink->clock && GST_IS_AUDIO_CLOCK (sink->clock) &&
- + GST_AUDIO_CLOCK_CAST (sink->clock)->func ==
- + (GstAudioClockGetTimeFunc) gst_audio_base_src_get_time);
- +}
- +
- static GstClockTime
- gst_audio_base_src_get_time (GstClock * clock, GstAudioBaseSrc * src)
- {
- @@ -555,6 +563,11 @@ gst_audio_base_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
- if (!gst_audio_ring_buffer_acquire (src->ringbuffer, spec))
- goto acquire_error;
-
- + /* If we use our own clock, we need to adjust the offset since it will now
- + * restart from zero */
- + if (gst_audio_base_src_is_self_provided_clock (src))
- + gst_audio_clock_reset (GST_AUDIO_CLOCK (src->clock), 0);
- +
- /* calculate actual latency and buffer times */
- spec->latency_time = spec->segsize * GST_MSECOND / (rate * bpf);
- spec->buffer_time =
- @@ -1142,9 +1155,7 @@ gst_audio_base_src_change_state (GstElement * element,
- /* Only post clock-provide messages if this is the clock that
- * we've created. If the subclass has overridden it the subclass
- * should post this messages whenever necessary */
- - if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) &&
- - GST_AUDIO_CLOCK_CAST (src->clock)->func ==
- - (GstAudioClockGetTimeFunc) gst_audio_base_src_get_time)
- + if (gst_audio_base_src_is_self_provided_clock (src))
- gst_element_post_message (element,
- gst_message_new_clock_provide (GST_OBJECT_CAST (element),
- src->clock, TRUE));
- @@ -1163,9 +1174,7 @@ gst_audio_base_src_change_state (GstElement * element,
- /* Only post clock-lost messages if this is the clock that
- * we've created. If the subclass has overridden it the subclass
- * should post this messages whenever necessary */
- - if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) &&
- - GST_AUDIO_CLOCK_CAST (src->clock)->func ==
- - (GstAudioClockGetTimeFunc) gst_audio_base_src_get_time)
- + if (gst_audio_base_src_is_self_provided_clock (src))
- gst_element_post_message (element,
- gst_message_new_clock_lost (GST_OBJECT_CAST (element), src->clock));
- gst_audio_ring_buffer_set_flushing (src->ringbuffer, TRUE);
- --
- 2.28.0
- From 63a3609a1b668e5bdab0a0b052bb8a6b1b7f62b8 Mon Sep 17 00:00:00 2001
- From: Jan Schmidt <jan@centricular.com>
- Date: Sat, 19 Aug 2023 01:00:16 +1000
- Subject: [PATCH] audio: Make sure to stop ringbuffer on error
- Add gst_audio_ring_buffer_set_errored() that will mark the
- ringbuffer as errored only if it is currently started or paused,
- so gst_audio_ringbuffer_stop() can be sure that the error
- state means that the ringbuffer was started and needs stop called.
- Fixes a crash with osxaudiosrc if the source element posts
- an error, because the ringbuffer would not get stopped and CoreAudio
- would continue trying to do callbacks.
- Also, anywhere that modifies the ringbuffer state, make sure to
- use atomic operations, to guarantee their visibility
- ---
- girs/GstAudio-1.0.gir | 15 ++++++
- .../gst-libs/gst/audio/gstaudiobasesrc.c | 2 +-
- .../gst-libs/gst/audio/gstaudioringbuffer.c | 50 ++++++++++++++++---
- .../gst-libs/gst/audio/gstaudioringbuffer.h | 3 ++
- 4 files changed, 62 insertions(+), 8 deletions(-)
- diff --git a/gst-libs/gst/audio/gstaudiobasesrc.c b/gst-libs/gst/audio/gstaudiobasesrc.c
- index 0dd7654e036..04916f36fdd 100644
- --- a/gst-libs/gst/audio/gstaudiobasesrc.c
- +++ b/gst-libs/gst/audio/gstaudiobasesrc.c
- @@ -1229,7 +1229,7 @@ gst_audio_base_src_post_message (GstElement * element, GstMessage * message)
- * flow error message */
- ret = GST_ELEMENT_CLASS (parent_class)->post_message (element, message);
-
- - g_atomic_int_set (&ringbuffer->state, GST_AUDIO_RING_BUFFER_STATE_ERROR);
- + gst_audio_ring_buffer_set_errored (ringbuffer);
- GST_AUDIO_RING_BUFFER_SIGNAL (ringbuffer);
- gst_object_unref (ringbuffer);
- } else {
- diff --git a/gst-libs/gst/audio/gstaudioringbuffer.c b/gst-libs/gst/audio/gstaudioringbuffer.c
- index c2319105840..a567f72af0f 100644
- --- a/gst-libs/gst/audio/gstaudioringbuffer.c
- +++ b/gst-libs/gst/audio/gstaudioringbuffer.c
- @@ -82,7 +82,7 @@ gst_audio_ring_buffer_init (GstAudioRingBuffer * ringbuffer)
- {
- ringbuffer->open = FALSE;
- ringbuffer->acquired = FALSE;
- - ringbuffer->state = GST_AUDIO_RING_BUFFER_STATE_STOPPED;
- + g_atomic_int_set (&ringbuffer->state, GST_AUDIO_RING_BUFFER_STATE_STOPPED);
- g_cond_init (&ringbuffer->cond);
- ringbuffer->waiting = 0;
- ringbuffer->empty_seg = NULL;
- @@ -1066,7 +1066,7 @@ gst_audio_ring_buffer_start (GstAudioRingBuffer * buf)
- }
-
- if (G_UNLIKELY (!res)) {
- - buf->state = GST_AUDIO_RING_BUFFER_STATE_PAUSED;
- + g_atomic_int_set (&buf->state, GST_AUDIO_RING_BUFFER_STATE_PAUSED);
- GST_DEBUG_OBJECT (buf, "failed to start");
- } else {
- GST_DEBUG_OBJECT (buf, "started");
- @@ -1097,6 +1097,34 @@ may_not_start:
- }
- }
-
- +/**
- + * gst_audio_ring_buffer_set_errored:
- + * @buf: the #GstAudioRingBuffer that has encountered an error
- + *
- + * Mark the ringbuffer as errored after it has started.
- + *
- + * MT safe.
- +
- + * Since: 1.24
- + */
- +void
- +gst_audio_ring_buffer_set_errored (GstAudioRingBuffer * buf)
- +{
- + gboolean res;
- +
- + /* If started set to errored */
- + res = g_atomic_int_compare_and_exchange (&buf->state,
- + GST_AUDIO_RING_BUFFER_STATE_STARTED, GST_AUDIO_RING_BUFFER_STATE_ERROR);
- + if (!res) {
- + GST_DEBUG_OBJECT (buf, "ringbuffer was not started, checking paused");
- + res = g_atomic_int_compare_and_exchange (&buf->state,
- + GST_AUDIO_RING_BUFFER_STATE_PAUSED, GST_AUDIO_RING_BUFFER_STATE_ERROR);
- + }
- + if (res) {
- + GST_DEBUG_OBJECT (buf, "ringbuffer is errored");
- + }
- +}
- +
- static gboolean
- gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf)
- {
- @@ -1121,7 +1149,8 @@ gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf)
- res = rclass->pause (buf);
-
- if (G_UNLIKELY (!res)) {
- - buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
- + /* Restore started state */
- + g_atomic_int_set (&buf->state, GST_AUDIO_RING_BUFFER_STATE_STARTED);
- GST_DEBUG_OBJECT (buf, "failed to pause");
- } else {
- GST_DEBUG_OBJECT (buf, "paused");
- @@ -1132,7 +1161,7 @@ gst_audio_ring_buffer_pause_unlocked (GstAudioRingBuffer * buf)
- not_started:
- {
- /* was not started */
- - GST_DEBUG_OBJECT (buf, "was not started");
- + GST_DEBUG_OBJECT (buf, "was not started (state %d)", buf->state);
- return TRUE;
- }
- }
- @@ -1214,9 +1243,16 @@ gst_audio_ring_buffer_stop (GstAudioRingBuffer * buf)
- GST_AUDIO_RING_BUFFER_STATE_PAUSED,
- GST_AUDIO_RING_BUFFER_STATE_STOPPED);
- if (!res) {
- - /* was not paused either, must have been stopped then */
- + GST_DEBUG_OBJECT (buf, "was not paused, try errored");
- + res = g_atomic_int_compare_and_exchange (&buf->state,
- + GST_AUDIO_RING_BUFFER_STATE_ERROR,
- + GST_AUDIO_RING_BUFFER_STATE_STOPPED);
- + }
- + if (!res) {
- + /* was not paused or stopped either, must have been stopped then */
- res = TRUE;
- - GST_DEBUG_OBJECT (buf, "was not paused, must have been stopped");
- + GST_DEBUG_OBJECT (buf,
- + "was not paused or errored, must have been stopped");
- goto done;
- }
- }
- @@ -1230,7 +1266,7 @@ gst_audio_ring_buffer_stop (GstAudioRingBuffer * buf)
- res = rclass->stop (buf);
-
- if (G_UNLIKELY (!res)) {
- - buf->state = GST_AUDIO_RING_BUFFER_STATE_STARTED;
- + g_atomic_int_set (&buf->state, GST_AUDIO_RING_BUFFER_STATE_STARTED);
- GST_DEBUG_OBJECT (buf, "failed to stop");
- } else {
- GST_DEBUG_OBJECT (buf, "stopped");
- diff --git a/gst-libs/gst/audio/gstaudioringbuffer.h b/gst-libs/gst/audio/gstaudioringbuffer.h
- index cde57cb457a..e188636145b 100644
- --- a/gst-libs/gst/audio/gstaudioringbuffer.h
- +++ b/gst-libs/gst/audio/gstaudioringbuffer.h
- @@ -379,6 +379,9 @@ gboolean gst_audio_ring_buffer_pause (GstAudioRingBuffer *buf);
- GST_AUDIO_API
- gboolean gst_audio_ring_buffer_stop (GstAudioRingBuffer *buf);
-
- +GST_AUDIO_API
- +void gst_audio_ring_buffer_set_errored (GstAudioRingBuffer *buf);
- +
- /* get status */
-
- GST_AUDIO_API
- --
- GitLab
|