From 85aee8e273dc02738753ff2a844bb77bd76883f5 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Sat, 6 Jan 2007 17:28:40 +0000 Subject: [PATCH] gst-libs/gst/audio/gstbaseaudiosink.c (gst_base_audio_sink_class_init) Original commit message from CVS: 2007-01-06 Andy Wingo * gst-libs/gst/audio/gstbaseaudiosink.c (gst_base_audio_sink_class_init) (gst_base_audio_sink_init): (gst_base_audio_sink_activate_pull): Add an activate_pull function to baseaudiosink, and tell basesink that we can work in pull mode. This way the ring buffer thread drives the pipeline directly, if pull mode is possible. There is some lingering nastiness regarding capsnego, however. (gst_base_audio_sink_callback): Implement the callback to pull data. This interface is a bit light, though -- it should get a GstFlowReturn return value at least. --- ChangeLog | 14 ++++++ gst-libs/gst/audio/gstbaseaudiosink.c | 80 +++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index aba77a3..de98d3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2007-01-06 Andy Wingo + + * gst-libs/gst/audio/gstbaseaudiosink.c + (gst_base_audio_sink_class_init) + (gst_base_audio_sink_init): + (gst_base_audio_sink_activate_pull): Add an activate_pull function + to baseaudiosink, and tell basesink that we can work in pull mode. + This way the ring buffer thread drives the pipeline directly, if + pull mode is possible. There is some lingering nastiness regarding + capsnego, however. + (gst_base_audio_sink_callback): Implement the callback to pull + data. This interface is a bit light, though -- it should get a + GstFlowReturn return value at least. + 2007-01-05 Tim-Philipp Müller * ext/ogg/gstoggdemux.c: (gst_ogg_pad_stream_out): diff --git a/gst-libs/gst/audio/gstbaseaudiosink.c b/gst-libs/gst/audio/gstbaseaudiosink.c index 3fc9a99..4eb8fea 100644 --- a/gst-libs/gst/audio/gstbaseaudiosink.c +++ b/gst-libs/gst/audio/gstbaseaudiosink.c @@ -85,6 +85,8 @@ static GstStateChangeReturn gst_base_audio_sink_async_play (GstBaseSink * basesink); static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement * element, GstStateChange transition); +static gboolean gst_base_audio_sink_activate_pull (GstBaseSink * basesink, + gboolean active); static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem); static GstClockTime gst_base_audio_sink_get_time (GstClock * clock, @@ -155,6 +157,8 @@ gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass) gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_sink_setcaps); gstbasesink_class->async_play = GST_DEBUG_FUNCPTR (gst_base_audio_sink_async_play); + gstbasesink_class->activate_pull = + GST_DEBUG_FUNCPTR (gst_base_audio_sink_activate_pull); } static void @@ -167,6 +171,9 @@ gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink, baseaudiosink->provided_clock = gst_audio_clock_new ("clock", (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink); + + GST_BASE_SINK (baseaudiosink)->can_activate_push = TRUE; + GST_BASE_SINK (baseaudiosink)->can_activate_pull = TRUE; } static void @@ -810,11 +817,80 @@ gst_base_audio_sink_create_ringbuffer (GstBaseAudioSink * sink) return buffer; } +static gboolean +gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active) +{ + gboolean ret; + GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink); + + if (active) { + GstCaps *sinkcaps, *peercaps, *caps; + + gst_ring_buffer_set_callback (sink->ringbuffer, + gst_base_audio_sink_callback, sink); + + /* need to spawn a thread to start pulling. that's the ring buffer thread, + which is started in ring_buffer_acquire(), which is called due to a sink + setcaps(). So we need to setcaps, which is tough because we don't know + exactly what caps we'll be getting. We can guess, though, and that's as + good as we're going to get without the user telling us explicitly e.g. + via a capsfilter before the sink. */ + sinkcaps = gst_pad_get_caps (basesink->sinkpad); + peercaps = gst_pad_peer_get_caps (basesink->sinkpad); + caps = gst_caps_intersect (sinkcaps, peercaps); + gst_caps_unref (sinkcaps); + gst_caps_unref (peercaps); + gst_caps_truncate (caps); + gst_pad_fixate_caps (basesink->sinkpad, caps); + + GST_DEBUG_OBJECT (sink, "initializing pull-mode ringbuffer with caps %" + GST_PTR_FORMAT, caps); + ret = gst_pad_set_caps (basesink->sinkpad, caps); + gst_caps_unref (caps); + } else { + gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL); + /* stop thread */ + ret = gst_ring_buffer_release (sink->ringbuffer); + } + + return ret; +} + static void gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len, gpointer user_data) { - /* GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (data); */ + GstBaseSink *basesink; + GstBaseAudioSink *sink; + GstBuffer *buf; + GstFlowReturn ret; + + basesink = GST_BASE_SINK (data); + sink = GST_BASE_AUDIO_SINK (data); + + /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we + will copy twice, once into data, once into DMA */ + GST_LOG_OBJECT (basesink, "pulling %d bytes to fill audio buffer", len); + ret = gst_pad_pull_range (basesink->sinkpad, basesink->offset, len, &buf); + if (ret != GST_FLOW_OK) + goto error; + + if (len != GST_BUFFER_SIZE (buf)) { + GST_INFO_OBJECT (basesink, "short read pulling from sink pad: %d<%d", + len, GST_BUFFER_SIZE (buf)); + len = MIN (GST_BUFFER_SIZE (buf), len); + } + + memcpy (data, GST_BUFFER_DATA (buf), len); + + return; + +error: + { + GST_WARNING_OBJECT (basesink, "Got flow error but can't return it: %d", + ret); + return; + } } /* should be called with the LOCK */ @@ -884,8 +960,6 @@ gst_base_audio_sink_change_state (GstElement * element, case GST_STATE_CHANGE_NULL_TO_READY: if (sink->ringbuffer == NULL) { sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink); - gst_ring_buffer_set_callback (sink->ringbuffer, - gst_base_audio_sink_callback, sink); } if (!gst_ring_buffer_open_device (sink->ringbuffer)) goto open_failed; -- 2.7.4