mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 02:00:33 +00:00
fix clock - seeking, xruns etc should be handled correctly now includes bugfix to not play the rest of the audio buff...
Original commit message from CVS: fix clock - seeking, xruns etc should be handled correctly now includes bugfix to not play the rest of the audio buffer when going PAUSED => READY
This commit is contained in:
parent
7877428028
commit
da25cbb0b3
2 changed files with 42 additions and 18 deletions
|
@ -970,7 +970,7 @@ gst_alsa_change_state (GstElement *element)
|
||||||
/* if device doesn't know how to pause, we just stop */
|
/* if device doesn't know how to pause, we just stop */
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
if (GST_FLAG_IS_SET (element, GST_ALSA_RUNNING))
|
if (GST_FLAG_IS_SET (element, GST_ALSA_RUNNING))
|
||||||
gst_alsa_drain_audio (this);
|
gst_alsa_close_audio (this);
|
||||||
/* clear format and pads */
|
/* clear format and pads */
|
||||||
g_free (this->format);
|
g_free (this->format);
|
||||||
this->format = NULL;
|
this->format = NULL;
|
||||||
|
@ -1147,7 +1147,7 @@ gst_alsa_start (GstAlsa *this)
|
||||||
avail = (gint) gst_alsa_update_avail (this);
|
avail = (gint) gst_alsa_update_avail (this);
|
||||||
if (avail < 0)
|
if (avail < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
this->transmitted = this->period_count * this->period_size - avail;
|
//this->transmitted = this->period_count * this->period_size - avail;
|
||||||
gst_alsa_clock_start (this->clock);
|
gst_alsa_clock_start (this->clock);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1209,7 +1209,8 @@ no_difference:
|
||||||
int samples = MIN (bytes, samplestamp - this->transmitted) *
|
int samples = MIN (bytes, samplestamp - this->transmitted) *
|
||||||
(element->numpads == 1 ? this->format->channels : 1);
|
(element->numpads == 1 ? this->format->channels : 1);
|
||||||
int size = samples * snd_pcm_format_physical_width (this->format->format) / 8;
|
int size = samples * snd_pcm_format_physical_width (this->format->format) / 8;
|
||||||
g_printerr ("Allocating %d bytes (%ld silent samples) now to resync to timestamp\n", size, MIN (bytes, samplestamp - this->transmitted));
|
g_printerr ("Allocating %d bytes (%ld samples) now to resync: sample %ld expected, but got %ld\n",
|
||||||
|
size, MIN (bytes, samplestamp - this->transmitted), this->transmitted, samplestamp);
|
||||||
pad->data = g_malloc (size);
|
pad->data = g_malloc (size);
|
||||||
if (!pad->data) {
|
if (!pad->data) {
|
||||||
g_warning ("GstAlsa: error allocating %d bytes, buffers unsynced now.", size);
|
g_warning ("GstAlsa: error allocating %d bytes, buffers unsynced now.", size);
|
||||||
|
@ -1432,6 +1433,11 @@ gst_alsa_sink_check_event (GstAlsa *this, gint pad_nr, GstEvent *event)
|
||||||
if (pad_nr != 0)
|
if (pad_nr != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (this->clock->start_time)) { /* if the clock is running */
|
||||||
|
g_assert (this->format);
|
||||||
|
/* adjust the start time */
|
||||||
|
this->clock->start_time += gst_alsa_samples_to_timestamp (this, this->transmitted);
|
||||||
|
}
|
||||||
this->transmitted = 0;
|
this->transmitted = 0;
|
||||||
/* FIXME: Notify the clock that we're at offset 0 again */
|
/* FIXME: Notify the clock that we're at offset 0 again */
|
||||||
break;
|
break;
|
||||||
|
@ -1445,7 +1451,7 @@ gst_alsa_sink_check_event (GstAlsa *this, gint pad_nr, GstEvent *event)
|
||||||
}
|
}
|
||||||
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
|
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
|
||||||
if (!gst_clock_handle_discont (GST_ELEMENT (this)->clock, value))
|
if (!gst_clock_handle_discont (GST_ELEMENT (this)->clock, value))
|
||||||
g_warning ("GstAlsa: clock couldn't handle discontinuity");
|
g_printerr ("GstAlsa: clock couldn't handle discontinuity\n");
|
||||||
}
|
}
|
||||||
if (!gst_event_discont_get_value (event, GST_FORMAT_UNITS, &value)) {
|
if (!gst_event_discont_get_value (event, GST_FORMAT_UNITS, &value)) {
|
||||||
if (!gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value)) {
|
if (!gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value)) {
|
||||||
|
@ -1461,10 +1467,13 @@ gst_alsa_sink_check_event (GstAlsa *this, gint pad_nr, GstEvent *event)
|
||||||
value = gst_alsa_bytes_to_samples (this, value);
|
value = gst_alsa_bytes_to_samples (this, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (this->clock->start_time)) { /* if the clock is running */
|
||||||
|
g_assert (this->format);
|
||||||
|
/* adjust the start time */
|
||||||
|
this->clock->start_time += gst_alsa_samples_to_timestamp (this, this->transmitted) -
|
||||||
|
gst_alsa_samples_to_timestamp (this, value);
|
||||||
|
}
|
||||||
this->transmitted = value;
|
this->transmitted = value;
|
||||||
if (snd_pcm_state (this->handle) == SND_PCM_STATE_RUNNING)
|
|
||||||
gst_alsa_clock_start (this->clock);
|
|
||||||
/* flush the current pad */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -1664,7 +1673,10 @@ gst_alsa_drain_audio (GstAlsa *this)
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_PLUGIN_INFO, "stopping alsa");
|
GST_DEBUG (GST_CAT_PLUGIN_INFO, "stopping alsa");
|
||||||
|
|
||||||
if (this->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (this->stream == SND_PCM_STREAM_PLAYBACK &&
|
||||||
|
(snd_pcm_state (this->handle) == SND_PCM_STATE_PAUSED ||
|
||||||
|
snd_pcm_state (this->handle) == SND_PCM_STATE_XRUN ||
|
||||||
|
snd_pcm_state (this->handle) == SND_PCM_STATE_RUNNING)) {
|
||||||
ERROR_CHECK (snd_pcm_drain (this->handle),
|
ERROR_CHECK (snd_pcm_drain (this->handle),
|
||||||
"couldn't stop and drain buffer: %s");
|
"couldn't stop and drain buffer: %s");
|
||||||
gst_alsa_clock_stop (this->clock);
|
gst_alsa_clock_stop (this->clock);
|
||||||
|
@ -1678,12 +1690,14 @@ static gboolean
|
||||||
gst_alsa_stop_audio (GstAlsa *this)
|
gst_alsa_stop_audio (GstAlsa *this)
|
||||||
{
|
{
|
||||||
g_assert (this != NULL);
|
g_assert (this != NULL);
|
||||||
g_return_val_if_fail (this != NULL, FALSE);
|
|
||||||
g_return_val_if_fail (this->handle != NULL, FALSE);
|
g_return_val_if_fail (this->handle != NULL, FALSE);
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_PLUGIN_INFO, "stopping alsa, skipping pending frames");
|
GST_DEBUG (GST_CAT_PLUGIN_INFO, "stopping alsa, skipping pending frames");
|
||||||
|
|
||||||
if (this->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (this->stream == SND_PCM_STREAM_PLAYBACK &&
|
||||||
|
(snd_pcm_state (this->handle) == SND_PCM_STATE_PAUSED ||
|
||||||
|
snd_pcm_state (this->handle) == SND_PCM_STATE_XRUN ||
|
||||||
|
snd_pcm_state (this->handle) == SND_PCM_STATE_RUNNING)) {
|
||||||
ERROR_CHECK (snd_pcm_drop (this->handle),
|
ERROR_CHECK (snd_pcm_drop (this->handle),
|
||||||
"couldn't stop (dropping frames): %s");
|
"couldn't stop (dropping frames): %s");
|
||||||
gst_alsa_clock_stop (this->clock);
|
gst_alsa_clock_stop (this->clock);
|
||||||
|
@ -1754,6 +1768,8 @@ static void
|
||||||
gst_alsa_clock_init (GstAlsaClock *clock)
|
gst_alsa_clock_init (GstAlsaClock *clock)
|
||||||
{
|
{
|
||||||
gst_object_set_name (GST_OBJECT (clock), "GstAlsaClock");
|
gst_object_set_name (GST_OBJECT (clock), "GstAlsaClock");
|
||||||
|
|
||||||
|
clock->start_time = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
GstAlsaClock*
|
GstAlsaClock*
|
||||||
gst_alsa_clock_new (gchar *name, GstAlsaClockGetTimeFunc get_time, GstAlsa *owner)
|
gst_alsa_clock_new (gchar *name, GstAlsaClockGetTimeFunc get_time, GstAlsa *owner)
|
||||||
|
@ -1776,28 +1792,36 @@ gst_alsa_clock_start (GstAlsaClock *clock)
|
||||||
GTimeVal timeval;
|
GTimeVal timeval;
|
||||||
g_get_current_time (&timeval);
|
g_get_current_time (&timeval);
|
||||||
|
|
||||||
|
g_assert (!GST_CLOCK_TIME_IS_VALID (clock->start_time));
|
||||||
|
|
||||||
if (clock->owner->format) {
|
if (clock->owner->format) {
|
||||||
clock->adjust = GST_TIMEVAL_TO_TIME (timeval) - clock->get_time (clock->owner);
|
clock->start_time = GST_TIMEVAL_TO_TIME (timeval) + clock->adjust - clock->get_time (clock->owner);
|
||||||
} else {
|
} else {
|
||||||
clock->adjust = GST_TIMEVAL_TO_TIME (timeval);
|
clock->start_time = GST_TIMEVAL_TO_TIME (timeval) + clock->adjust;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
gst_alsa_clock_stop (GstAlsaClock *clock)
|
gst_alsa_clock_stop (GstAlsaClock *clock)
|
||||||
{
|
{
|
||||||
clock->adjust = 0;
|
GTimeVal timeval;
|
||||||
|
g_get_current_time (&timeval);
|
||||||
|
|
||||||
|
g_assert (GST_CLOCK_TIME_IS_VALID (clock->start_time));
|
||||||
|
|
||||||
|
clock->adjust += GST_TIMEVAL_TO_TIME (timeval) - clock->start_time - clock->get_time (clock->owner);
|
||||||
|
clock->start_time = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
static GstClockTime
|
static GstClockTime
|
||||||
gst_alsa_clock_get_internal_time (GstClock *clock)
|
gst_alsa_clock_get_internal_time (GstClock *clock)
|
||||||
{
|
{
|
||||||
GstAlsaClock *alsa_clock = GST_ALSA_CLOCK (clock);
|
GstAlsaClock *alsa_clock = GST_ALSA_CLOCK (clock);
|
||||||
|
|
||||||
if (alsa_clock->adjust) {
|
if (GST_CLOCK_TIME_IS_VALID (alsa_clock->start_time)) {
|
||||||
return alsa_clock->get_time (alsa_clock->owner) + alsa_clock->adjust;
|
return alsa_clock->get_time (alsa_clock->owner) + alsa_clock->start_time;
|
||||||
} else {
|
} else {
|
||||||
GTimeVal timeval;
|
GTimeVal timeval;
|
||||||
g_get_current_time (&timeval);
|
g_get_current_time (&timeval);
|
||||||
return GST_TIMEVAL_TO_TIME (timeval);
|
return GST_TIMEVAL_TO_TIME (timeval) + alsa_clock->adjust;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static guint64
|
static guint64
|
||||||
|
@ -1892,7 +1916,6 @@ gst_alsa_timestamp_to_samples (GstAlsa *this, GstClockTime time)
|
||||||
{
|
{
|
||||||
return (snd_pcm_uframes_t) ((time * this->format->rate + this->format->rate / 2) / GST_SECOND);
|
return (snd_pcm_uframes_t) ((time * this->format->rate + this->format->rate / 2) / GST_SECOND);
|
||||||
}
|
}
|
||||||
/* assumes that this->format != NULL */
|
|
||||||
static inline GstClockTime
|
static inline GstClockTime
|
||||||
gst_alsa_samples_to_timestamp (GstAlsa *this, snd_pcm_uframes_t samples)
|
gst_alsa_samples_to_timestamp (GstAlsa *this, snd_pcm_uframes_t samples)
|
||||||
{
|
{
|
||||||
|
|
|
@ -155,7 +155,8 @@ struct _GstAlsaClock {
|
||||||
GstAlsaClockGetTimeFunc get_time;
|
GstAlsaClockGetTimeFunc get_time;
|
||||||
GstAlsa * owner;
|
GstAlsa * owner;
|
||||||
|
|
||||||
GstClockTimeDiff adjust; /* time_of_clock - time_of_element at sync point */
|
GstClockTimeDiff adjust; /* adjustment to real clock (recalculated when stopping) */
|
||||||
|
GstClockTime start_time; /* time when the stream started (NONE when stopped) */
|
||||||
|
|
||||||
GstClockTime last_unlock; /* time of last unlock request */
|
GstClockTime last_unlock; /* time of last unlock request */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue