From a169abc6794b9f12834030cc435a680db0fc9cb6 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 30 Jan 2006 16:19:33 +0000 Subject: [PATCH] gst-libs/gst/audio/gstaudiosink.c: Implement pause that does not wait for completion. Original commit message from CVS: * gst-libs/gst/audio/gstaudiosink.c: (gst_audioringbuffer_class_init), (gst_audioringbuffer_release), (gst_audioringbuffer_pause): Implement pause that does not wait for completion. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): Don't drop buffers when going to PAUSED but perform preroll on remaining samples now that core base class supports this. * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_release), (gst_ring_buffer_pause_unlocked), (gst_ring_buffer_stop), (gst_ring_buffer_commit): Pause should not signal waiters. Implement return value of _commit correctly. --- ChangeLog | 18 ++++++++++++++++++ common | 2 +- gst-libs/gst/audio/gstaudiosink.c | 23 ++++++++++++++++++++++- gst-libs/gst/audio/gstbaseaudiosink.c | 35 ++++++++++++++++++++++++++++++++--- gst-libs/gst/audio/gstringbuffer.c | 25 +++++++++++++------------ 5 files changed, 86 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 012e5a3..4f3a51c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2006-01-30 Wim Taymans + + * gst-libs/gst/audio/gstaudiosink.c: + (gst_audioringbuffer_class_init), (gst_audioringbuffer_release), + (gst_audioringbuffer_pause): + Implement pause that does not wait for completion. + + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): + Don't drop buffers when going to PAUSED but perform preroll on + remaining samples now that core base class supports this. + + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_release), + (gst_ring_buffer_pause_unlocked), (gst_ring_buffer_stop), + (gst_ring_buffer_commit): + Pause should not signal waiters. + Implement return value of _commit correctly. + 2006-01-30 Andy Wingo * tests/check/Makefile.am (check_vorbis): Add pipelines/vorbisenc. diff --git a/common b/common index bc43253..0b93085 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit bc4325349e8d0ec90aa5c5e74566880cc2e82527 +Subproject commit 0b93085188e83fe678ec5ded2823cd7c24dfa843 diff --git a/gst-libs/gst/audio/gstaudiosink.c b/gst-libs/gst/audio/gstaudiosink.c index 67c0260..1c3a9fe 100644 --- a/gst-libs/gst/audio/gstaudiosink.c +++ b/gst-libs/gst/audio/gstaudiosink.c @@ -77,6 +77,7 @@ static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec); static gboolean gst_audioringbuffer_release (GstRingBuffer * buf); static gboolean gst_audioringbuffer_start (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf); static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf); static guint gst_audioringbuffer_delay (GstRingBuffer * buf); @@ -132,7 +133,7 @@ gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass) gstringbuffer_class->release = GST_DEBUG_FUNCPTR (gst_audioringbuffer_release); gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start); - gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop); + gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_audioringbuffer_pause); gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start); gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop); @@ -348,6 +349,7 @@ gst_audioringbuffer_release (GstRingBuffer * buf) abuf = GST_AUDIORING_BUFFER (buf); abuf->running = FALSE; + GST_DEBUG ("signal wait"); GST_AUDIORING_BUFFER_SIGNAL (buf); GST_OBJECT_UNLOCK (buf); @@ -389,6 +391,25 @@ gst_audioringbuffer_start (GstRingBuffer * buf) } static gboolean +gst_audioringbuffer_pause (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + /* unblock any pending writes to the audio device */ + if (csink->reset) { + GST_DEBUG ("reset..."); + csink->reset (sink); + GST_DEBUG ("reset done"); + } + + return TRUE; +} + +static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf) { GstAudioSink *sink; diff --git a/gst-libs/gst/audio/gstbaseaudiosink.c b/gst-libs/gst/audio/gstbaseaudiosink.c index d291b38..61e8790 100644 --- a/gst-libs/gst/audio/gstbaseaudiosink.c +++ b/gst-libs/gst/audio/gstbaseaudiosink.c @@ -406,7 +406,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) gint64 diff, ctime, cstop; guint8 *data; guint size; - guint samples; + guint samples, written; gint bps; gdouble crate = 1.0; GstClockTime crate_num; @@ -458,6 +458,8 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) * arriving before the segment.start or after segment.stop are to be * thrown away. All samples should also be clipped to the segment * boundaries */ + /* let's calc stop based on the number of samples in the buffer instead + * of trusting the DURATION */ stop = time + gst_util_uint64_scale_int (samples, GST_SECOND, ringbuf->spec.rate); @@ -536,7 +538,27 @@ no_sync: /* the next sample should be current sample and its length */ sink->next_sample = render_offset + samples; - samples = gst_ring_buffer_commit (ringbuf, render_offset, data, samples); + do { + written = gst_ring_buffer_commit (ringbuf, render_offset, data, samples); + GST_DEBUG_OBJECT (sink, "wrote %u of %u", written, samples); + /* if we wrote all, we're done */ + if (written == samples) + break; + + /* else something interrupted us */ + GST_DEBUG_OBJECT (sink, "wait for preroll..."); + bsink->have_preroll = TRUE; + GST_PAD_PREROLL_WAIT (bsink->sinkpad); + bsink->have_preroll = FALSE; + GST_DEBUG_OBJECT (sink, "preroll done"); + if (G_UNLIKELY (bsink->flushing)) + goto stopping; + GST_DEBUG_OBJECT (sink, "continue after preroll"); + + render_offset += written; + samples -= written; + data += written * bps; + } while (TRUE); if (GST_CLOCK_TIME_IS_VALID (stop) && stop >= bsink->segment.stop) { GST_DEBUG_OBJECT (sink, @@ -569,6 +591,11 @@ wrong_size: ("sink received buffer of wrong size.")); return GST_FLOW_ERROR; } +stopping: + { + GST_DEBUG_OBJECT (sink, "ringbuffer is stopping"); + return GST_FLOW_WRONG_STATE; + } } GstRingBuffer * @@ -644,6 +671,9 @@ gst_base_audio_sink_change_state (GstElement * element, GST_OBJECT_UNLOCK (sink); break; } + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + gst_ring_buffer_pause (sink->ringbuffer); + break; case GST_STATE_CHANGE_PAUSED_TO_READY: gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); break; @@ -655,7 +685,6 @@ gst_base_audio_sink_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - gst_ring_buffer_pause (sink->ringbuffer); /* slop slaving ourselves to the master, if any */ gst_clock_set_master (sink->provided_clock, NULL); break; diff --git a/gst-libs/gst/audio/gstringbuffer.c b/gst-libs/gst/audio/gstringbuffer.c index b1a8ae3..5615c00 100644 --- a/gst-libs/gst/audio/gstringbuffer.c +++ b/gst-libs/gst/audio/gstringbuffer.c @@ -654,6 +654,7 @@ gst_ring_buffer_release (GstRingBuffer * buf) res = rclass->release (buf); /* signal any waiters */ + GST_DEBUG_OBJECT (buf, "signal waiter"); GST_RING_BUFFER_SIGNAL (buf); if (!res) @@ -820,9 +821,6 @@ gst_ring_buffer_pause_unlocked (GstRingBuffer * buf) goto done; } - /* signal any waiters */ - GST_RING_BUFFER_SIGNAL (buf); - rclass = GST_RING_BUFFER_GET_CLASS (buf); if (rclass->pause) res = rclass->pause (buf); @@ -906,6 +904,7 @@ gst_ring_buffer_stop (GstRingBuffer * buf) } /* signal any waiters */ + GST_DEBUG_OBJECT (buf, "signal waiter"); GST_RING_BUFFER_SIGNAL (buf); rclass = GST_RING_BUFFER_GET_CLASS (buf); @@ -1127,6 +1126,7 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data, gint segdone; gint segsize, segtotal, bps, sps; guint8 *dest; + guint to_write; g_return_val_if_fail (buf != NULL, -1); g_return_val_if_fail (buf->data != NULL, -1); @@ -1138,8 +1138,9 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data, bps = buf->spec.bytes_per_sample; sps = buf->samples_per_seg; + to_write = len; /* write out all samples */ - while (len > 0) { + while (to_write > 0) { gint sampleslen; gint writeseg, sampleoff; @@ -1158,14 +1159,14 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data, diff = writeseg - segdone; GST_DEBUG - ("pointer at %d, sample %llu, write to %d-%d, len %d, diff %d, segtotal %d, segsize %d", - segdone, sample, writeseg, sampleoff, len, diff, segtotal, sps); + ("pointer at %d, sample %llu, write to %d-%d, to_write %d, diff %d, segtotal %d, segsize %d", + segdone, sample, writeseg, sampleoff, to_write, diff, segtotal, sps); /* segment too far ahead, we need to drop */ if (diff < 0) { /* we need to drop one segment at a time, pretend we wrote a * segment. */ - sampleslen = MIN (sps, len); + sampleslen = MIN (sps, to_write); goto next; } @@ -1181,27 +1182,27 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data, /* we can write now */ writeseg = writeseg % segtotal; - sampleslen = MIN (sps - sampleoff, len); + sampleslen = MIN (sps - sampleoff, to_write); - GST_DEBUG_OBJECT (buf, "write @%p seg %d, off %d, len %d", + GST_DEBUG_OBJECT (buf, "write @%p seg %d, off %d, sampleslen %d", dest + writeseg * segsize, writeseg, sampleoff, sampleslen); memcpy (dest + (writeseg * segsize) + (sampleoff * bps), data, (sampleslen * bps)); next: - len -= sampleslen; + to_write -= sampleslen; sample += sampleslen; data += sampleslen * bps; } - return len; + return len - to_write; /* ERRORS */ not_started: { GST_DEBUG_OBJECT (buf, "stopped processing"); - return -1; + return len - to_write; } } -- 2.7.4