mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-22 05:56:31 +00:00
audiosink: expose more audioringbuffer vmethods to child sinks
The newly exposed vmethods are pause, resume, stop and clear_all. The existing reset vmethod is deprecated. The audio sink will fallback to calling reset if pause or stop are not provided and will fallback to calling start if resume is not provided. There is no default clear_all implementation. Existing audio sinks continue to work as before. This change is useful for sinks that need to distinguish between a pause and a stop (currently both are handled by a reset) and is needed for https://bugzilla.gnome.org/show_bug.cgi?id=788362 https://bugzilla.gnome.org/show_bug.cgi?id=788361
This commit is contained in:
parent
f1d3307e03
commit
0dc1b6049e
4 changed files with 92 additions and 12 deletions
|
@ -1291,6 +1291,12 @@ gst_audio_ring_buffer_set_sample (GstAudioRingBuffer * buf, guint64 sample)
|
|||
sample, buf->segbase);
|
||||
}
|
||||
|
||||
/**
|
||||
* default_clear_all:
|
||||
* @buf: the #GstAudioRingBuffer to clear
|
||||
*
|
||||
* Fill the ringbuffer with silence.
|
||||
*/
|
||||
static void
|
||||
default_clear_all (GstAudioRingBuffer * buf)
|
||||
{
|
||||
|
@ -1311,7 +1317,7 @@ default_clear_all (GstAudioRingBuffer * buf)
|
|||
* gst_audio_ring_buffer_clear_all:
|
||||
* @buf: the #GstAudioRingBuffer to clear
|
||||
*
|
||||
* Fill the ringbuffer with silence.
|
||||
* Clear all samples from the ringbuffer.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
|
|
|
@ -234,7 +234,10 @@ struct _GstAudioRingBuffer {
|
|||
* @activate: activate the thread that starts pulling and monitoring the
|
||||
* consumed segments in the device.
|
||||
* @commit: write samples into the ringbuffer
|
||||
* @clear_all: clear the entire ringbuffer.
|
||||
* @clear_all: Optional.
|
||||
* Clear the entire ringbuffer.
|
||||
* Subclasses should chain up to the parent implementation to
|
||||
* invoke the default handler.
|
||||
*
|
||||
* The vmethods that subclasses can override to implement the ringbuffer.
|
||||
*/
|
||||
|
|
|
@ -117,10 +117,12 @@ static gboolean gst_audio_sink_ring_buffer_acquire (GstAudioRingBuffer * buf,
|
|||
static gboolean gst_audio_sink_ring_buffer_release (GstAudioRingBuffer * buf);
|
||||
static gboolean gst_audio_sink_ring_buffer_start (GstAudioRingBuffer * buf);
|
||||
static gboolean gst_audio_sink_ring_buffer_pause (GstAudioRingBuffer * buf);
|
||||
static gboolean gst_audio_sink_ring_buffer_resume (GstAudioRingBuffer * buf);
|
||||
static gboolean gst_audio_sink_ring_buffer_stop (GstAudioRingBuffer * buf);
|
||||
static guint gst_audio_sink_ring_buffer_delay (GstAudioRingBuffer * buf);
|
||||
static gboolean gst_audio_sink_ring_buffer_activate (GstAudioRingBuffer * buf,
|
||||
gboolean active);
|
||||
static void gst_audio_sink_ring_buffer_clear_all (GstAudioRingBuffer * buf);
|
||||
|
||||
/* ringbuffer abstract base class */
|
||||
static GType
|
||||
|
@ -176,14 +178,15 @@ gst_audio_sink_ring_buffer_class_init (GstAudioSinkRingBufferClass * klass)
|
|||
gstringbuffer_class->pause =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_pause);
|
||||
gstringbuffer_class->resume =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_start);
|
||||
GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_resume);
|
||||
gstringbuffer_class->stop =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_stop);
|
||||
|
||||
gstringbuffer_class->delay =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_delay);
|
||||
gstringbuffer_class->activate =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_activate);
|
||||
gstringbuffer_class->clear_all =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_clear_all);
|
||||
}
|
||||
|
||||
typedef gint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
|
||||
|
@ -531,12 +534,36 @@ gst_audio_sink_ring_buffer_pause (GstAudioRingBuffer * buf)
|
|||
csink = GST_AUDIO_SINK_GET_CLASS (sink);
|
||||
|
||||
/* unblock any pending writes to the audio device */
|
||||
if (csink->reset) {
|
||||
if (csink->pause) {
|
||||
GST_DEBUG_OBJECT (sink, "pause...");
|
||||
csink->pause (sink);
|
||||
GST_DEBUG_OBJECT (sink, "pause done");
|
||||
} else if (csink->reset) {
|
||||
/* fallback to reset for audio sinks that don't provide pause */
|
||||
GST_DEBUG_OBJECT (sink, "reset...");
|
||||
csink->reset (sink);
|
||||
GST_DEBUG_OBJECT (sink, "reset done");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_audio_sink_ring_buffer_resume (GstAudioRingBuffer * buf)
|
||||
{
|
||||
GstAudioSink *sink;
|
||||
GstAudioSinkClass *csink;
|
||||
|
||||
sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
|
||||
csink = GST_AUDIO_SINK_GET_CLASS (sink);
|
||||
|
||||
if (csink->resume) {
|
||||
GST_DEBUG_OBJECT (sink, "resume...");
|
||||
csink->resume (sink);
|
||||
GST_DEBUG_OBJECT (sink, "resume done");
|
||||
} else {
|
||||
/* fallback to start for audio sinks that don't provide resume */
|
||||
gst_audio_sink_ring_buffer_start (buf);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -550,7 +577,12 @@ gst_audio_sink_ring_buffer_stop (GstAudioRingBuffer * buf)
|
|||
csink = GST_AUDIO_SINK_GET_CLASS (sink);
|
||||
|
||||
/* unblock any pending writes to the audio device */
|
||||
if (csink->reset) {
|
||||
if (csink->stop) {
|
||||
GST_DEBUG_OBJECT (sink, "stop...");
|
||||
csink->stop (sink);
|
||||
GST_DEBUG_OBJECT (sink, "stop done");
|
||||
} else if (csink->reset) {
|
||||
/* fallback to reset for audio sinks that don't provide stop */
|
||||
GST_DEBUG_OBJECT (sink, "reset...");
|
||||
csink->reset (sink);
|
||||
GST_DEBUG_OBJECT (sink, "reset done");
|
||||
|
@ -582,6 +614,24 @@ gst_audio_sink_ring_buffer_delay (GstAudioRingBuffer * buf)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_sink_ring_buffer_clear_all (GstAudioRingBuffer * buf)
|
||||
{
|
||||
GstAudioSink *sink;
|
||||
GstAudioSinkClass *csink;
|
||||
|
||||
sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
|
||||
csink = GST_AUDIO_SINK_GET_CLASS (sink);
|
||||
|
||||
if (csink->clear_all) {
|
||||
GST_DEBUG_OBJECT (sink, "clear all");
|
||||
csink->clear_all (sink);
|
||||
}
|
||||
|
||||
/* chain up to the parent implementation */
|
||||
ring_parent_class->clear_all (buf);
|
||||
}
|
||||
|
||||
/* AudioSink signals and args */
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -66,12 +66,25 @@ struct _GstAudioSink {
|
|||
* @unprepare: Undo operations done in prepare.
|
||||
* @close: Close the device.
|
||||
* @write: Write data to the device.
|
||||
* @delay: Return how many frames are still in the device. This is used to
|
||||
* drive the synchronisation.
|
||||
* This vmethod is allowed to block until all the data is written.
|
||||
* If such is the case then it is expected that pause, stop and
|
||||
* reset will unblock the write when called.
|
||||
* @delay: Return how many frames are still in the device. Participates in
|
||||
* computing the time for audio clocks and drives the synchronisation.
|
||||
* @reset: Returns as quickly as possible from a write and flush any pending
|
||||
* samples from the device.
|
||||
*
|
||||
* #GstAudioSink class. Override the vmethods to implement functionality.
|
||||
* This vmethod is deprecated. Please provide pause and stop instead.
|
||||
* @pause: Pause the device and unblock write as fast as possible.
|
||||
* For retro compatibility, the audio sink will fallback
|
||||
* to calling reset if this vmethod is not provided.
|
||||
* @resume: Resume the device.
|
||||
* For retro compatibility, the audio sink will fallback
|
||||
* to calling start if this vmethod is not provided.
|
||||
* @stop: Stop the device and unblock write as fast as possible.
|
||||
* Pending samples are flushed from the device.
|
||||
* For retro compatibility, the audio sink will fallback
|
||||
* to calling reset if this vmethod is not provided.
|
||||
* @clear-all: Clear the device.
|
||||
*/
|
||||
struct _GstAudioSinkClass {
|
||||
GstAudioBaseSinkClass parent_class;
|
||||
|
@ -90,11 +103,19 @@ struct _GstAudioSinkClass {
|
|||
gint (*write) (GstAudioSink *sink, gpointer data, guint length);
|
||||
/* get number of frames queued in the device */
|
||||
guint (*delay) (GstAudioSink *sink);
|
||||
/* reset the audio device, unblock from a write */
|
||||
/* deprecated: reset the audio device, unblock from a write */
|
||||
void (*reset) (GstAudioSink *sink);
|
||||
/* pause the audio device, unblock from a write */
|
||||
void (*pause) (GstAudioSink *sink);
|
||||
/* resume the audio device */
|
||||
void (*resume) (GstAudioSink *sink);
|
||||
/* stop the audio device, unblock from a write */
|
||||
void (*stop) (GstAudioSink *sink);
|
||||
/* clear the audio device */
|
||||
void (*clear_all) (GstAudioSink *sink);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
gpointer _gst_reserved[GST_PADDING - 4];
|
||||
};
|
||||
|
||||
GST_AUDIO_API
|
||||
|
|
Loading…
Reference in a new issue