mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
alsasink: pause/resume
alsasink can now detect a resume, stop and pause. The sink is now properly paused using snd_pcm_pause(), and without losing any data
This commit is contained in:
parent
feb1e24347
commit
5d3c948572
2 changed files with 95 additions and 9 deletions
|
@ -94,7 +94,9 @@ static gboolean gst_alsasink_close (GstAudioSink * asink);
|
|||
static gint gst_alsasink_write (GstAudioSink * asink, gpointer data,
|
||||
guint length);
|
||||
static guint gst_alsasink_delay (GstAudioSink * asink);
|
||||
static void gst_alsasink_reset (GstAudioSink * asink);
|
||||
static void gst_alsasink_pause (GstAudioSink * asink);
|
||||
static void gst_alsasink_resume (GstAudioSink * asink);
|
||||
static void gst_alsasink_stop (GstAudioSink * asink);
|
||||
static gboolean gst_alsasink_acceptcaps (GstAlsaSink * alsa, GstCaps * caps);
|
||||
static GstBuffer *gst_alsasink_payload (GstAudioBaseSink * sink,
|
||||
GstBuffer * buf);
|
||||
|
@ -181,7 +183,9 @@ gst_alsasink_class_init (GstAlsaSinkClass * klass)
|
|||
gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink_close);
|
||||
gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink_write);
|
||||
gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink_delay);
|
||||
gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink_reset);
|
||||
gstaudiosink_class->stop = GST_DEBUG_FUNCPTR (gst_alsasink_stop);
|
||||
gstaudiosink_class->pause = GST_DEBUG_FUNCPTR (gst_alsasink_pause);
|
||||
gstaudiosink_class->resume = GST_DEBUG_FUNCPTR (gst_alsasink_resume);
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_DEVICE,
|
||||
g_param_spec_string ("device", "Device",
|
||||
|
@ -259,6 +263,9 @@ gst_alsasink_init (GstAlsaSink * alsasink)
|
|||
alsasink->device = g_strdup (DEFAULT_DEVICE);
|
||||
alsasink->handle = NULL;
|
||||
alsasink->cached_caps = NULL;
|
||||
alsasink->is_paused = FALSE;
|
||||
alsasink->after_paused = FALSE;
|
||||
alsasink->hw_support_pause = FALSE;
|
||||
g_mutex_init (&alsasink->alsa_lock);
|
||||
g_mutex_init (&alsasink->delay_lock);
|
||||
|
||||
|
@ -545,6 +552,11 @@ retry:
|
|||
GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
|
||||
alsa->period_size);
|
||||
|
||||
/* Check if hardware supports pause */
|
||||
alsa->hw_support_pause = snd_pcm_hw_params_can_pause (params);
|
||||
GST_DEBUG_OBJECT (alsa, "Hw support pause: %s",
|
||||
alsa->hw_support_pause ? "yes" : "no");
|
||||
|
||||
snd_pcm_hw_params_free (params);
|
||||
return 0;
|
||||
|
||||
|
@ -1084,12 +1096,23 @@ gst_alsasink_delay (GstAudioSink * asink)
|
|||
{
|
||||
GstAlsaSink *alsa;
|
||||
snd_pcm_sframes_t delay;
|
||||
int res;
|
||||
int res = 0;
|
||||
|
||||
alsa = GST_ALSA_SINK (asink);
|
||||
|
||||
GST_DELAY_SINK_LOCK (asink);
|
||||
res = snd_pcm_delay (alsa->handle, &delay);
|
||||
if (alsa->is_paused == TRUE) {
|
||||
delay = alsa->pos_in_buffer;
|
||||
alsa->is_paused = FALSE;
|
||||
alsa->after_paused = TRUE;
|
||||
} else {
|
||||
if (alsa->after_paused == TRUE) {
|
||||
delay = alsa->pos_in_buffer;
|
||||
alsa->after_paused = FALSE;
|
||||
} else {
|
||||
res = snd_pcm_delay (alsa->handle, &delay);
|
||||
}
|
||||
}
|
||||
GST_DELAY_SINK_UNLOCK (asink);
|
||||
if (G_UNLIKELY (res < 0)) {
|
||||
/* on errors, report 0 delay */
|
||||
|
@ -1106,7 +1129,65 @@ gst_alsasink_delay (GstAudioSink * asink)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_alsasink_reset (GstAudioSink * asink)
|
||||
gst_alsasink_pause (GstAudioSink * asink)
|
||||
{
|
||||
GstAlsaSink *alsa;
|
||||
gint err;
|
||||
snd_pcm_sframes_t delay;
|
||||
|
||||
alsa = GST_ALSA_SINK (asink);
|
||||
|
||||
if (alsa->hw_support_pause == TRUE) {
|
||||
GST_ALSA_SINK_LOCK (asink);
|
||||
snd_pcm_delay (alsa->handle, &delay);
|
||||
alsa->pos_in_buffer = delay;
|
||||
CHECK (snd_pcm_pause (alsa->handle, 1), pause_error);
|
||||
GST_DEBUG_OBJECT (alsa, "pause done");
|
||||
alsa->is_paused = TRUE;
|
||||
GST_ALSA_SINK_UNLOCK (asink);
|
||||
} else {
|
||||
gst_alsasink_stop (asink);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
pause_error:
|
||||
{
|
||||
GST_ERROR_OBJECT (alsa, "alsa-pause: pcm pause error: %s",
|
||||
snd_strerror (err));
|
||||
GST_ALSA_SINK_UNLOCK (asink);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_alsasink_resume (GstAudioSink * asink)
|
||||
{
|
||||
GstAlsaSink *alsa;
|
||||
gint err;
|
||||
|
||||
alsa = GST_ALSA_SINK (asink);
|
||||
|
||||
if (alsa->hw_support_pause == TRUE) {
|
||||
GST_ALSA_SINK_LOCK (asink);
|
||||
CHECK (snd_pcm_pause (alsa->handle, 0), resume_error);
|
||||
GST_DEBUG_OBJECT (alsa, "resume done");
|
||||
GST_ALSA_SINK_UNLOCK (asink);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
resume_error:
|
||||
{
|
||||
GST_ERROR_OBJECT (alsa, "alsa-resume: pcm resume error: %s",
|
||||
snd_strerror (err));
|
||||
GST_ALSA_SINK_UNLOCK (asink);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_alsasink_stop (GstAudioSink * asink)
|
||||
{
|
||||
GstAlsaSink *alsa;
|
||||
gint err;
|
||||
|
@ -1118,7 +1199,7 @@ gst_alsasink_reset (GstAudioSink * asink)
|
|||
CHECK (snd_pcm_drop (alsa->handle), drop_error);
|
||||
GST_DEBUG_OBJECT (alsa, "prepare");
|
||||
CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
|
||||
GST_DEBUG_OBJECT (alsa, "reset done");
|
||||
GST_DEBUG_OBJECT (alsa, "stop done");
|
||||
GST_ALSA_SINK_UNLOCK (asink);
|
||||
|
||||
return;
|
||||
|
@ -1126,14 +1207,14 @@ gst_alsasink_reset (GstAudioSink * asink)
|
|||
/* ERRORS */
|
||||
drop_error:
|
||||
{
|
||||
GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
|
||||
GST_ERROR_OBJECT (alsa, "alsa-stop: pcm drop error: %s",
|
||||
snd_strerror (err));
|
||||
GST_ALSA_SINK_UNLOCK (asink);
|
||||
return;
|
||||
}
|
||||
prepare_error:
|
||||
{
|
||||
GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
|
||||
GST_ERROR_OBJECT (alsa, "alsa-stop: pcm prepare error: %s",
|
||||
snd_strerror (err));
|
||||
GST_ALSA_SINK_UNLOCK (asink);
|
||||
return;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
|
||||
*
|
||||
* gstalsasink.h:
|
||||
* gstalsasink.h:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
@ -74,6 +74,11 @@ struct _GstAlsaSink {
|
|||
|
||||
GstCaps *cached_caps;
|
||||
|
||||
gboolean is_paused;
|
||||
gboolean after_paused;
|
||||
gboolean hw_support_pause;
|
||||
snd_pcm_sframes_t pos_in_buffer;
|
||||
|
||||
GMutex alsa_lock;
|
||||
GMutex delay_lock;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue