From 96c2a1531831dd62d2e800267e14e4bbc787f676 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Wed, 23 Jun 2004 16:57:16 +0000 Subject: [PATCH] merge back from release Original commit message from CVS: merge back from release --- ChangeLog | 9 ++++ ext/alsa/gstalsa.c | 122 ++++++++----------------------------------------- ext/alsa/gstalsa.h | 6 --- ext/alsa/gstalsasink.c | 12 +++-- 4 files changed, 35 insertions(+), 114 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5da97a0..f0fc6f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-06-23 Thomas Vander Stichele + + * ext/alsa/gstalsa.c: (gst_alsa_init), (gst_alsa_dispose), + (gst_alsa_change_state), (gst_alsa_update_avail), + (gst_alsa_xrun_recovery): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + merge back changes from release + 2004-06-23 Wim Taymans * gst/audiorate/gstaudiorate.c: (gst_audiorate_class_init), diff --git a/ext/alsa/gstalsa.c b/ext/alsa/gstalsa.c index 3915598..e9c2138 100644 --- a/ext/alsa/gstalsa.c +++ b/ext/alsa/gstalsa.c @@ -203,12 +203,6 @@ static void gst_alsa_init (GstAlsa * this) { this->device = g_strdup ("default"); - g_assert (snd_pcm_status_malloc (&(this->status)) == 0); - - this->clock = gst_alsa_clock_new ("alsaclock", gst_alsa_get_time, this); - /* we hold a ref to our clock until we're disposed */ - gst_object_ref (GST_OBJECT (this->clock)); - gst_object_sink (GST_OBJECT (this->clock)); GST_FLAG_SET (this, GST_ELEMENT_EVENT_AWARE); GST_FLAG_SET (this, GST_ELEMENT_THREAD_SUGGESTED); @@ -220,9 +214,6 @@ gst_alsa_dispose (GObject * object) GstAlsa *this = GST_ALSA (object); g_free (this->device); - this->device = NULL; - snd_pcm_status_free (this->status); - this->status = NULL; if (this->clock) gst_object_unparent (GST_OBJECT (this->clock)); @@ -319,63 +310,6 @@ gst_alsa_get_property (GObject * object, guint prop_id, GValue * value, } } -/** - * ask ALSA for current time using htstamp - * FIXME: This is not very accurate, should use alsa timers instead. - * htstamp seems to use the system clock instead of the hw clock. - * We also use an ugly hack for now to substract the number of queued - * samples in the device from the system time, this makes sure that other - * plugins timestamp their samples with the right time but makes the - * clock a little unstable. A good way to fix this is to get the exact amount - * of samples that were produced by ALSA but I can't find a way to get that - * information.. oh well.. ALSA has enough methods, there is bound to be at - * least 1 way of getting the info... - */ -GstClockTime -gst_alsa_get_time (GstAlsa * this) -{ - int err; - snd_htimestamp_t timestamp; - GstClockTime time, ideal; - GstClockTime availtime; - snd_pcm_sframes_t avail; - - if ((err = snd_pcm_status (this->handle, this->status)) < 0) { - GST_WARNING_OBJECT (this, "could not get snd_pcm_status"); - } - - /* see how many samples are still in the buffer */ - avail = snd_pcm_status_get_avail (this->status); - availtime = gst_alsa_samples_to_timestamp (this, avail); - - /* get the clock time */ - snd_pcm_status_get_htstamp (this->status, ×tamp); - - /* time = GST_TIMESPEC_TO_TIME (timestamp); */ - /* we have to compensate the time for the number of queued samples - * in the buffer */ - time = - timestamp.tv_sec * GST_SECOND + timestamp.tv_nsec * GST_NSECOND - - availtime; - ideal = - this->clock_base + gst_alsa_samples_to_timestamp (this, - this->transmitted) - availtime; - - GST_DEBUG_OBJECT (this, "clock time %lld, diff to ideal %lld\n", time, - time - ideal); - - GST_LOG_OBJECT (this, "ALSA reports time of %" GST_TIME_FORMAT, - GST_TIME_ARGS (time)); - - return time; -} - -void -gst_alsa_clock_update (GstAlsa * this, GstClockTime ideal) -{ - -} - static const GList * gst_alsa_probe_get_properties (GstPropertyProbe * probe) { @@ -1152,7 +1086,6 @@ gst_alsa_change_state (GstElement * element) gst_alsa_start_audio (this))) return GST_STATE_FAILURE; this->transmitted = 0; - this->clock_base = GST_CLOCK_TIME_NONE; break; case GST_STATE_PAUSED_TO_PLAYING: if (snd_pcm_state (this->handle) == SND_PCM_STATE_PAUSED) { @@ -1222,22 +1155,14 @@ gst_alsa_set_clock (GstElement * element, GstClock * clock) inline snd_pcm_sframes_t gst_alsa_update_avail (GstAlsa * this) { - snd_pcm_sframes_t avail = -1; + snd_pcm_sframes_t avail = snd_pcm_avail_update (this->handle); - while (avail < 0) { - avail = snd_pcm_avail_update (this->handle); - if (avail < 0) { - if (avail == -EPIPE) { - gst_alsa_xrun_recovery (this); - } else { - GST_WARNING_OBJECT (this, "unknown ALSA avail_update return value (%d)", - (int) avail); - } - } - if (snd_pcm_state (this->handle) != SND_PCM_STATE_RUNNING) { - if (!gst_alsa_start (this)) { - return 0; - } + if (avail < 0) { + if (avail == -EPIPE) { + gst_alsa_xrun_recovery (this); + } else { + GST_WARNING_OBJECT (this, "unknown ALSA avail_update return value (%d)", + (int) avail); } } return avail; @@ -1319,7 +1244,13 @@ gst_alsa_xrun_recovery (GstAlsa * this) GST_ERROR_OBJECT (this, "status error: %s", snd_strerror (err)); if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN) { - GstClockTime elemnow; + struct timeval now, diff, tstamp; + + gettimeofday (&now, 0); + snd_pcm_status_get_trigger_tstamp (status, &tstamp); + timersub (&now, &tstamp, &diff); + GST_INFO_OBJECT (this, "alsa: xrun of at least %.3f msecs", + diff.tv_sec * 1000 + diff.tv_usec / 1000.0); /* if we're allowed to recover, ... */ if (this->autorecover) { @@ -1333,27 +1264,12 @@ gst_alsa_xrun_recovery (GstAlsa * this) this->period_count *= 2; } } + } - if ((err = snd_pcm_prepare (this->handle)) < 0) { - GST_ERROR_OBJECT (this, "prepare error: %s", snd_strerror (err)); - return FALSE; - } - /* The strategy to recover the timestamps from the xrun is to take the - * current element time and pretend we just sent all the samples up to - * that time. This will result in an offset discontinuity in the next - * buffer along with the correct timestamp on that buffer */ - elemnow = gst_element_get_time (GST_ELEMENT (this)); - this->transmitted = gst_alsa_timestamp_to_samples (this, elemnow); - GST_DEBUG_OBJECT (this, "XRun!!!! pretending we transmitted %lld samples", - this->transmitted); - - } else { - /* something else happened, reset the device */ - if (!(gst_alsa_stop_audio (this) && gst_alsa_start_audio (this))) { - GST_ELEMENT_ERROR (this, RESOURCE, FAILED, (NULL), - ("Error restarting audio after xrun")); - return FALSE; - } + if (!(gst_alsa_stop_audio (this) && gst_alsa_start_audio (this))) { + GST_ELEMENT_ERROR (this, RESOURCE, FAILED, (NULL), + ("Error restarting audio after xrun")); + return FALSE; } return TRUE; diff --git a/ext/alsa/gstalsa.h b/ext/alsa/gstalsa.h index 9fac58d..b499b66 100644 --- a/ext/alsa/gstalsa.h +++ b/ext/alsa/gstalsa.h @@ -156,7 +156,6 @@ struct _GstAlsa { /* clocking */ GstAlsaClock * clock; /* our provided clock */ - GstClockTime clock_base; /* adjusted clock base time */ snd_pcm_uframes_t transmitted; /* samples transmitted since last sync This thing actually is our master clock. We will event insert silent samples or @@ -165,7 +164,6 @@ struct _GstAlsa { GstClockTime max_discont; /* max difference between current playback timestamp and buffers timestamps */ - snd_pcm_status_t *status; }; struct _GstAlsaClass { @@ -193,10 +191,6 @@ GstCaps * gst_alsa_caps (snd_pcm_format_t format, gint rate, gint channels); -GstClockTime gst_alsa_get_time (GstAlsa * this); -void gst_alsa_clock_update (GstAlsa * this, GstClockTime ideal); - - /* audio processing functions */ inline snd_pcm_sframes_t gst_alsa_update_avail (GstAlsa * this); inline gboolean gst_alsa_pcm_wait (GstAlsa * this); diff --git a/ext/alsa/gstalsasink.c b/ext/alsa/gstalsasink.c index 049ce7e..5959b46 100644 --- a/ext/alsa/gstalsasink.c +++ b/ext/alsa/gstalsasink.c @@ -220,13 +220,15 @@ gst_alsa_sink_check_event (GstAlsaSink * sink, gint pad_nr) GST_SECOND * this->transmitted / this->format->rate - gst_alsa_sink_get_time (this); if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) { - gst_element_set_time_delay (GST_ELEMENT (this), value, delay); - } else if (this->format && - (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value) || - gst_event_discont_get_value (event, GST_FORMAT_BYTES, + gst_element_set_time_delay (GST_ELEMENT (this), MIN (value, delay), + delay); + } else if (this->format + && (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value) + || gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value))) { value = gst_alsa_samples_to_timestamp (this, value); - gst_element_set_time_delay (GST_ELEMENT (this), value, delay); + gst_element_set_time_delay (GST_ELEMENT (this), MIN (value, delay), + delay); } else { GST_WARNING_OBJECT (this, "couldn't extract time from discont event. Bad things might happen!"); -- 2.7.4