merge back from release

Original commit message from CVS:
merge back from release
This commit is contained in:
Thomas Vander Stichele 2004-06-23 16:57:16 +00:00
parent 13377326ca
commit 96c2a15318
4 changed files with 35 additions and 114 deletions

View file

@ -1,3 +1,12 @@
2004-06-23 Thomas Vander Stichele <thomas at apestaart dot org>
* 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 <wim@fluendo.com> 2004-06-23 Wim Taymans <wim@fluendo.com>
* gst/audiorate/gstaudiorate.c: (gst_audiorate_class_init), * gst/audiorate/gstaudiorate.c: (gst_audiorate_class_init),

View file

@ -203,12 +203,6 @@ static void
gst_alsa_init (GstAlsa * this) gst_alsa_init (GstAlsa * this)
{ {
this->device = g_strdup ("default"); 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_EVENT_AWARE);
GST_FLAG_SET (this, GST_ELEMENT_THREAD_SUGGESTED); GST_FLAG_SET (this, GST_ELEMENT_THREAD_SUGGESTED);
@ -220,9 +214,6 @@ gst_alsa_dispose (GObject * object)
GstAlsa *this = GST_ALSA (object); GstAlsa *this = GST_ALSA (object);
g_free (this->device); g_free (this->device);
this->device = NULL;
snd_pcm_status_free (this->status);
this->status = NULL;
if (this->clock) if (this->clock)
gst_object_unparent (GST_OBJECT (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, &timestamp);
/* 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 * static const GList *
gst_alsa_probe_get_properties (GstPropertyProbe * probe) gst_alsa_probe_get_properties (GstPropertyProbe * probe)
{ {
@ -1152,7 +1086,6 @@ gst_alsa_change_state (GstElement * element)
gst_alsa_start_audio (this))) gst_alsa_start_audio (this)))
return GST_STATE_FAILURE; return GST_STATE_FAILURE;
this->transmitted = 0; this->transmitted = 0;
this->clock_base = GST_CLOCK_TIME_NONE;
break; break;
case GST_STATE_PAUSED_TO_PLAYING: case GST_STATE_PAUSED_TO_PLAYING:
if (snd_pcm_state (this->handle) == SND_PCM_STATE_PAUSED) { 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 inline snd_pcm_sframes_t
gst_alsa_update_avail (GstAlsa * this) 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) { if (avail < 0) {
avail = snd_pcm_avail_update (this->handle); if (avail == -EPIPE) {
if (avail < 0) { gst_alsa_xrun_recovery (this);
if (avail == -EPIPE) { } else {
gst_alsa_xrun_recovery (this); GST_WARNING_OBJECT (this, "unknown ALSA avail_update return value (%d)",
} else { (int) avail);
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;
}
} }
} }
return avail; return avail;
@ -1319,7 +1244,13 @@ gst_alsa_xrun_recovery (GstAlsa * this)
GST_ERROR_OBJECT (this, "status error: %s", snd_strerror (err)); GST_ERROR_OBJECT (this, "status error: %s", snd_strerror (err));
if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN) { 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 we're allowed to recover, ... */
if (this->autorecover) { if (this->autorecover) {
@ -1333,27 +1264,12 @@ gst_alsa_xrun_recovery (GstAlsa * this)
this->period_count *= 2; this->period_count *= 2;
} }
} }
}
if ((err = snd_pcm_prepare (this->handle)) < 0) { if (!(gst_alsa_stop_audio (this) && gst_alsa_start_audio (this))) {
GST_ERROR_OBJECT (this, "prepare error: %s", snd_strerror (err)); GST_ELEMENT_ERROR (this, RESOURCE, FAILED, (NULL),
return FALSE; ("Error restarting audio after xrun"));
} 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;
}
} }
return TRUE; return TRUE;

View file

@ -156,7 +156,6 @@ struct _GstAlsa {
/* clocking */ /* clocking */
GstAlsaClock * clock; /* our provided clock */ GstAlsaClock * clock; /* our provided clock */
GstClockTime clock_base; /* adjusted clock base time */
snd_pcm_uframes_t transmitted; /* samples transmitted since last sync snd_pcm_uframes_t transmitted; /* samples transmitted since last sync
This thing actually is our master clock. This thing actually is our master clock.
We will event insert silent samples or We will event insert silent samples or
@ -165,7 +164,6 @@ struct _GstAlsa {
GstClockTime max_discont; /* max difference between current GstClockTime max_discont; /* max difference between current
playback timestamp and buffers timestamps playback timestamp and buffers timestamps
*/ */
snd_pcm_status_t *status;
}; };
struct _GstAlsaClass { struct _GstAlsaClass {
@ -193,10 +191,6 @@ GstCaps * gst_alsa_caps (snd_pcm_format_t format,
gint rate, gint rate,
gint channels); gint channels);
GstClockTime gst_alsa_get_time (GstAlsa * this);
void gst_alsa_clock_update (GstAlsa * this, GstClockTime ideal);
/* audio processing functions */ /* audio processing functions */
inline snd_pcm_sframes_t gst_alsa_update_avail (GstAlsa * this); inline snd_pcm_sframes_t gst_alsa_update_avail (GstAlsa * this);
inline gboolean gst_alsa_pcm_wait (GstAlsa * this); inline gboolean gst_alsa_pcm_wait (GstAlsa * this);

View file

@ -220,13 +220,15 @@ gst_alsa_sink_check_event (GstAlsaSink * sink, gint pad_nr)
GST_SECOND * this->transmitted / this->format->rate - GST_SECOND * this->transmitted / this->format->rate -
gst_alsa_sink_get_time (this); gst_alsa_sink_get_time (this);
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) { if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
gst_element_set_time_delay (GST_ELEMENT (this), value, delay); gst_element_set_time_delay (GST_ELEMENT (this), MIN (value, delay),
} else if (this->format && delay);
(gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value) || } else if (this->format
gst_event_discont_get_value (event, GST_FORMAT_BYTES, && (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value)
|| gst_event_discont_get_value (event, GST_FORMAT_BYTES,
&value))) { &value))) {
value = gst_alsa_samples_to_timestamp (this, 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 { } else {
GST_WARNING_OBJECT (this, GST_WARNING_OBJECT (this,
"couldn't extract time from discont event. Bad things might happen!"); "couldn't extract time from discont event. Bad things might happen!");