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.
This commit is contained in:
Wim Taymans 2006-01-30 16:19:33 +00:00
parent 0ad84fae5d
commit a169abc679
5 changed files with 86 additions and 17 deletions

View file

@ -1,3 +1,21 @@
2006-01-30 Wim Taymans <wim@fluendo.com>
* 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 <wingo@pobox.com> 2006-01-30 Andy Wingo <wingo@pobox.com>
* tests/check/Makefile.am (check_vorbis): Add pipelines/vorbisenc. * tests/check/Makefile.am (check_vorbis): Add pipelines/vorbisenc.

2
common

@ -1 +1 @@
Subproject commit bc4325349e8d0ec90aa5c5e74566880cc2e82527 Subproject commit 0b93085188e83fe678ec5ded2823cd7c24dfa843

View file

@ -77,6 +77,7 @@ static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
GstRingBufferSpec * spec); GstRingBufferSpec * spec);
static gboolean gst_audioringbuffer_release (GstRingBuffer * buf); static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
static gboolean gst_audioringbuffer_start (GstRingBuffer * buf); static gboolean gst_audioringbuffer_start (GstRingBuffer * buf);
static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf);
static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf); static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
static guint gst_audioringbuffer_delay (GstRingBuffer * buf); static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
@ -132,7 +133,7 @@ gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass)
gstringbuffer_class->release = gstringbuffer_class->release =
GST_DEBUG_FUNCPTR (gst_audioringbuffer_release); GST_DEBUG_FUNCPTR (gst_audioringbuffer_release);
gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start); 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->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop); gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
@ -348,6 +349,7 @@ gst_audioringbuffer_release (GstRingBuffer * buf)
abuf = GST_AUDIORING_BUFFER (buf); abuf = GST_AUDIORING_BUFFER (buf);
abuf->running = FALSE; abuf->running = FALSE;
GST_DEBUG ("signal wait");
GST_AUDIORING_BUFFER_SIGNAL (buf); GST_AUDIORING_BUFFER_SIGNAL (buf);
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
@ -388,6 +390,25 @@ gst_audioringbuffer_start (GstRingBuffer * buf)
return TRUE; return TRUE;
} }
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 static gboolean
gst_audioringbuffer_stop (GstRingBuffer * buf) gst_audioringbuffer_stop (GstRingBuffer * buf)
{ {

View file

@ -406,7 +406,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
gint64 diff, ctime, cstop; gint64 diff, ctime, cstop;
guint8 *data; guint8 *data;
guint size; guint size;
guint samples; guint samples, written;
gint bps; gint bps;
gdouble crate = 1.0; gdouble crate = 1.0;
GstClockTime crate_num; 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 * arriving before the segment.start or after segment.stop are to be
* thrown away. All samples should also be clipped to the segment * thrown away. All samples should also be clipped to the segment
* boundaries */ * boundaries */
/* let's calc stop based on the number of samples in the buffer instead
* of trusting the DURATION */
stop = stop =
time + gst_util_uint64_scale_int (samples, GST_SECOND, time + gst_util_uint64_scale_int (samples, GST_SECOND,
ringbuf->spec.rate); ringbuf->spec.rate);
@ -536,7 +538,27 @@ no_sync:
/* the next sample should be current sample and its length */ /* the next sample should be current sample and its length */
sink->next_sample = render_offset + samples; 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) { if (GST_CLOCK_TIME_IS_VALID (stop) && stop >= bsink->segment.stop) {
GST_DEBUG_OBJECT (sink, GST_DEBUG_OBJECT (sink,
@ -569,6 +591,11 @@ wrong_size:
("sink received buffer of wrong size.")); ("sink received buffer of wrong size."));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
stopping:
{
GST_DEBUG_OBJECT (sink, "ringbuffer is stopping");
return GST_FLOW_WRONG_STATE;
}
} }
GstRingBuffer * GstRingBuffer *
@ -644,6 +671,9 @@ gst_base_audio_sink_change_state (GstElement * element,
GST_OBJECT_UNLOCK (sink); GST_OBJECT_UNLOCK (sink);
break; break;
} }
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
gst_ring_buffer_pause (sink->ringbuffer);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
break; break;
@ -655,7 +685,6 @@ gst_base_audio_sink_change_state (GstElement * element,
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
gst_ring_buffer_pause (sink->ringbuffer);
/* slop slaving ourselves to the master, if any */ /* slop slaving ourselves to the master, if any */
gst_clock_set_master (sink->provided_clock, NULL); gst_clock_set_master (sink->provided_clock, NULL);
break; break;

View file

@ -654,6 +654,7 @@ gst_ring_buffer_release (GstRingBuffer * buf)
res = rclass->release (buf); res = rclass->release (buf);
/* signal any waiters */ /* signal any waiters */
GST_DEBUG_OBJECT (buf, "signal waiter");
GST_RING_BUFFER_SIGNAL (buf); GST_RING_BUFFER_SIGNAL (buf);
if (!res) if (!res)
@ -820,9 +821,6 @@ gst_ring_buffer_pause_unlocked (GstRingBuffer * buf)
goto done; goto done;
} }
/* signal any waiters */
GST_RING_BUFFER_SIGNAL (buf);
rclass = GST_RING_BUFFER_GET_CLASS (buf); rclass = GST_RING_BUFFER_GET_CLASS (buf);
if (rclass->pause) if (rclass->pause)
res = rclass->pause (buf); res = rclass->pause (buf);
@ -906,6 +904,7 @@ gst_ring_buffer_stop (GstRingBuffer * buf)
} }
/* signal any waiters */ /* signal any waiters */
GST_DEBUG_OBJECT (buf, "signal waiter");
GST_RING_BUFFER_SIGNAL (buf); GST_RING_BUFFER_SIGNAL (buf);
rclass = GST_RING_BUFFER_GET_CLASS (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 segdone;
gint segsize, segtotal, bps, sps; gint segsize, segtotal, bps, sps;
guint8 *dest; guint8 *dest;
guint to_write;
g_return_val_if_fail (buf != NULL, -1); g_return_val_if_fail (buf != NULL, -1);
g_return_val_if_fail (buf->data != 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; bps = buf->spec.bytes_per_sample;
sps = buf->samples_per_seg; sps = buf->samples_per_seg;
to_write = len;
/* write out all samples */ /* write out all samples */
while (len > 0) { while (to_write > 0) {
gint sampleslen; gint sampleslen;
gint writeseg, sampleoff; gint writeseg, sampleoff;
@ -1158,14 +1159,14 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data,
diff = writeseg - segdone; diff = writeseg - segdone;
GST_DEBUG GST_DEBUG
("pointer at %d, sample %llu, write to %d-%d, len %d, diff %d, segtotal %d, segsize %d", ("pointer at %d, sample %llu, write to %d-%d, to_write %d, diff %d, segtotal %d, segsize %d",
segdone, sample, writeseg, sampleoff, len, diff, segtotal, sps); segdone, sample, writeseg, sampleoff, to_write, diff, segtotal, sps);
/* segment too far ahead, we need to drop */ /* segment too far ahead, we need to drop */
if (diff < 0) { if (diff < 0) {
/* we need to drop one segment at a time, pretend we wrote a /* we need to drop one segment at a time, pretend we wrote a
* segment. */ * segment. */
sampleslen = MIN (sps, len); sampleslen = MIN (sps, to_write);
goto next; goto next;
} }
@ -1181,27 +1182,27 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data,
/* we can write now */ /* we can write now */
writeseg = writeseg % segtotal; 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); dest + writeseg * segsize, writeseg, sampleoff, sampleslen);
memcpy (dest + (writeseg * segsize) + (sampleoff * bps), data, memcpy (dest + (writeseg * segsize) + (sampleoff * bps), data,
(sampleslen * bps)); (sampleslen * bps));
next: next:
len -= sampleslen; to_write -= sampleslen;
sample += sampleslen; sample += sampleslen;
data += sampleslen * bps; data += sampleslen * bps;
} }
return len; return len - to_write;
/* ERRORS */ /* ERRORS */
not_started: not_started:
{ {
GST_DEBUG_OBJECT (buf, "stopped processing"); GST_DEBUG_OBJECT (buf, "stopped processing");
return -1; return len - to_write;
} }
} }