mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-05 14:02:26 +00:00
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:
parent
0ad84fae5d
commit
a169abc679
5 changed files with 86 additions and 17 deletions
18
ChangeLog
18
ChangeLog
|
@ -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
2
common
|
@ -1 +1 @@
|
||||||
Subproject commit bc4325349e8d0ec90aa5c5e74566880cc2e82527
|
Subproject commit 0b93085188e83fe678ec5ded2823cd7c24dfa843
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue