gst-plugins-base: alsasrc: fail gracefully when ALSA does not give timestamps
Sebastian Dröge
slomo at kemper.freedesktop.org
Mon Oct 3 02:14:22 PDT 2011
Module: gst-plugins-base
Branch: master
Commit: c7282a5718c7f31f84fb31b2c38fab0f9a38e2b0
URL: http://cgit.freedesktop.org/gstreamer/gst-plugins-base/commit/?id=c7282a5718c7f31f84fb31b2c38fab0f9a38e2b0
Author: Vincent Penquerc'h <vincent.penquerch at collabora.co.uk>
Date: Tue Sep 27 00:26:29 2011 +0100
alsasrc: fail gracefully when ALSA does not give timestamps
https://bugzilla.gnome.org/show_bug.cgi?id=660170
---
ext/alsa/gstalsasrc.c | 40 +++++++++++++++++++++++++++++++++++-----
ext/alsa/gstalsasrc.h | 1 +
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/ext/alsa/gstalsasrc.c b/ext/alsa/gstalsasrc.c
index cce52ea..3e7ce5f 100644
--- a/ext/alsa/gstalsasrc.c
+++ b/ext/alsa/gstalsasrc.c
@@ -254,37 +254,63 @@ gst_alsasrc_get_timestamp (GstAlsaSrc * src)
snd_htimestamp_t tstamp;
GstClockTime timestamp;
snd_pcm_uframes_t availmax;
+ gint64 offset;
GST_DEBUG_OBJECT (src, "Getting alsa timestamp!");
if (!src) {
GST_ERROR_OBJECT (src, "No alsa handle created yet !");
- return 0;
+ return GST_CLOCK_TIME_NONE;
}
if (snd_pcm_status_malloc (&status) != 0) {
GST_ERROR_OBJECT (src, "snd_pcm_status_malloc failed");
+ return GST_CLOCK_TIME_NONE;
}
if (snd_pcm_status (src->handle, status) != 0) {
GST_ERROR_OBJECT (src, "snd_pcm_status failed");
+ snd_pcm_status_free (status);
+ return GST_CLOCK_TIME_NONE;
}
/* get high resolution time stamp from driver */
snd_pcm_status_get_htstamp (status, &tstamp);
timestamp = GST_TIMESPEC_TO_TIME (tstamp);
+ GST_DEBUG_OBJECT (src, "Base ts: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (timestamp));
+ if (timestamp == 0) {
+ /* This timestamp is supposed to represent the last sample, so 0 (which
+ can be returned on some ALSA setups (such as mine)) must mean that it
+ is invalid, unless there's just one sample, but we'll ignore that. */
+ GST_WARNING_OBJECT (src,
+ "No timestamp returned from snd_pcm_status_get_htstamp");
+ return GST_CLOCK_TIME_NONE;
+ }
/* Max available frames sets the depth of the buffer */
availmax = snd_pcm_status_get_avail_max (status);
/* Compensate the fact that the timestamp references the last sample */
- timestamp -= gst_util_uint64_scale_int (availmax * 2, GST_SECOND, src->rate);
+ offset = -gst_util_uint64_scale_int (availmax * 2, GST_SECOND, src->rate);
/* Compensate for the delay until the package is available */
- timestamp += gst_util_uint64_scale_int (snd_pcm_status_get_delay (status),
+ offset += gst_util_uint64_scale_int (snd_pcm_status_get_delay (status),
GST_SECOND, src->rate);
snd_pcm_status_free (status);
+ /* just in case, should not happen */
+ if (-offset > timestamp)
+ timestamp = 0;
+ else
+ timestamp -= offset;
+
+ /* Take first ts into account */
+ if (src->first_alsa_ts == GST_CLOCK_TIME_NONE) {
+ src->first_alsa_ts = timestamp;
+ }
+ timestamp -= src->first_alsa_ts;
+
GST_DEBUG_OBJECT (src, "ALSA timestamp : %" GST_TIME_FORMAT,
GST_TIME_ARGS (timestamp));
return timestamp;
@@ -384,8 +410,10 @@ gst_alsasrc_create (GstBaseSrc * bsrc, guint64 offset, guint length,
ret =
GST_BASE_SRC_CLASS (parent_class)->create (bsrc, offset, length, outbuf);
if (asrc->driver_timestamps == TRUE && *outbuf) {
- GST_BUFFER_TIMESTAMP (*outbuf) =
- gst_alsasrc_get_timestamp ((GstAlsaSrc *) bsrc);
+ GstClockTime ts = gst_alsasrc_get_timestamp (asrc);
+ if (GST_CLOCK_TIME_IS_VALID (ts)) {
+ GST_BUFFER_TIMESTAMP (*outbuf) = ts;
+ }
}
return ret;
@@ -399,6 +427,7 @@ gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
alsasrc->cached_caps = NULL;
alsasrc->driver_timestamps = FALSE;
+ alsasrc->first_alsa_ts = GST_CLOCK_TIME_NONE;
alsasrc->alsa_lock = g_mutex_new ();
}
@@ -943,6 +972,7 @@ gst_alsasrc_reset (GstAudioSrc * asrc)
GST_DEBUG_OBJECT (alsa, "prepare");
CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
GST_DEBUG_OBJECT (alsa, "reset done");
+ alsa->first_alsa_ts = GST_CLOCK_TIME_NONE;
GST_ALSA_SRC_UNLOCK (asrc);
return;
diff --git a/ext/alsa/gstalsasrc.h b/ext/alsa/gstalsasrc.h
index 7072ab7..ba192be 100644
--- a/ext/alsa/gstalsasrc.h
+++ b/ext/alsa/gstalsasrc.h
@@ -65,6 +65,7 @@ struct _GstAlsaSrc {
guint channels;
gint bytes_per_sample;
gboolean driver_timestamps;
+ GstClockTime first_alsa_ts;
guint buffer_time;
guint period_time;
More information about the gstreamer-commits
mailing list