summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2004-06-17 14:10:21 +0000
committerWim Taymans <wim.taymans@gmail.com>2004-06-17 14:10:21 +0000
commita48818210de4cef95e9a30503ba7bb04f0f3a9ac (patch)
treea6aaa2022939eb4535065ceecf44ae7e12985094
parent7face56b420df8de21a33ee57345188b1a0cee3c (diff)
ext/alsa/: Make the xrun code timestamp and offset the buffers correctly. moved the clock to the base class, use alsa...
Original commit message from CVS: * ext/alsa/gstalsa.c: (gst_alsa_init), (gst_alsa_dispose), (gst_alsa_get_time), (gst_alsa_xrun_recovery): * ext/alsa/gstalsa.h: * ext/alsa/gstalsaclock.c: (gst_alsa_clock_get_type): * ext/alsa/gstalsasrc.c: (gst_alsa_src_init), (gst_alsa_src_loop), (gst_alsa_src_change_state): * ext/alsa/gstalsasrc.h: Make the xrun code timestamp and offset the buffers correctly. moved the clock to the base class, use alsa methods to get time. Do correct timestamping on outgoing buffers.
-rw-r--r--ChangeLog13
-rw-r--r--ext/alsa/gstalsa.c40
-rw-r--r--ext/alsa/gstalsa.h3
-rw-r--r--ext/alsa/gstalsasrc.c76
-rw-r--r--ext/alsa/gstalsasrc.h2
5 files changed, 99 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index 4189da6b9..340084867 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2004-06-17 Wim Taymans <wim@fluendo.com>
+ * ext/alsa/gstalsa.c: (gst_alsa_init), (gst_alsa_dispose),
+ (gst_alsa_get_time), (gst_alsa_xrun_recovery):
+ * ext/alsa/gstalsa.h:
+ * ext/alsa/gstalsaclock.c: (gst_alsa_clock_get_type):
+ * ext/alsa/gstalsasrc.c: (gst_alsa_src_init), (gst_alsa_src_loop),
+ (gst_alsa_src_change_state):
+ * ext/alsa/gstalsasrc.h:
+ Make the xrun code timestamp and offset the buffers correctly.
+ moved the clock to the base class, use alsa methods to get time.
+ Do correct timestamping on outgoing buffers.
+
+2004-06-17 Wim Taymans <wim@fluendo.com>
+
* gst/audiorate/Makefile.am:
* gst/audiorate/gstaudiorate.c: (gst_audiorate_get_type),
(gst_audiorate_base_init), (gst_audiorate_class_init),
diff --git a/ext/alsa/gstalsa.c b/ext/alsa/gstalsa.c
index e9c21388e..ef151b793 100644
--- a/ext/alsa/gstalsa.c
+++ b/ext/alsa/gstalsa.c
@@ -203,6 +203,12 @@ 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);
@@ -214,6 +220,9 @@ 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));
@@ -310,6 +319,33 @@ 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.
+ */
+GstClockTime
+gst_alsa_get_time (GstAlsa * this)
+{
+ int err;
+ snd_htimestamp_t timestamp;
+ GstClockTime time;
+
+ if ((err = snd_pcm_status (this->handle, this->status)) < 0) {
+ GST_WARNING_OBJECT (this, "could not get snd_pcm_status");
+ }
+
+ snd_pcm_status_get_htstamp (this->status, &timestamp);
+
+ /* time = GST_TIMESPEC_TO_TIME (timestamp); */
+ time = timestamp.tv_sec * GST_SECOND + timestamp.tv_nsec * GST_NSECOND;
+
+ GST_LOG_OBJECT (this, "ALSA reports time of %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (time));
+
+ return time;
+}
+
static const GList *
gst_alsa_probe_get_properties (GstPropertyProbe * probe)
{
@@ -1252,6 +1288,10 @@ gst_alsa_xrun_recovery (GstAlsa * this)
GST_INFO_OBJECT (this, "alsa: xrun of at least %.3f msecs",
diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+ /* start new timestamps from the current time */
+ this->transmitted = gst_alsa_timestamp_to_samples (this,
+ gst_element_get_time (GST_ELEMENT (this)));
+
/* if we're allowed to recover, ... */
if (this->autorecover) {
/* ... then increase the period size or buffer size / period count to
diff --git a/ext/alsa/gstalsa.h b/ext/alsa/gstalsa.h
index b499b668d..be7ae1bf1 100644
--- a/ext/alsa/gstalsa.h
+++ b/ext/alsa/gstalsa.h
@@ -164,6 +164,7 @@ struct _GstAlsa {
GstClockTime max_discont; /* max difference between current
playback timestamp and buffers timestamps
*/
+ snd_pcm_status_t *status;
};
struct _GstAlsaClass {
@@ -191,6 +192,8 @@ GstCaps * gst_alsa_caps (snd_pcm_format_t format,
gint rate,
gint channels);
+GstClockTime gst_alsa_get_time (GstAlsa * this);
+
/* 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/gstalsasrc.c b/ext/alsa/gstalsasrc.c
index db50d040b..05703d223 100644
--- a/ext/alsa/gstalsasrc.c
+++ b/ext/alsa/gstalsasrc.c
@@ -44,8 +44,6 @@ static void gst_alsa_src_loop (GstElement * element);
static void gst_alsa_src_flush (GstAlsaSrc * src);
static GstElementStateReturn gst_alsa_src_change_state (GstElement * element);
-static GstClockTime gst_alsa_src_get_time (GstAlsa * this);
-
static GstAlsa *src_parent_class = NULL;
static GstPadTemplate *
@@ -118,6 +116,7 @@ gst_alsa_src_class_init (gpointer g_class, gpointer class_data)
element_class->change_state = gst_alsa_src_change_state;
}
+
static void
gst_alsa_src_init (GstAlsaSrc * src)
{
@@ -128,14 +127,9 @@ gst_alsa_src_init (GstAlsaSrc * src)
gst_pad_set_getcaps_function (this->pad[0], gst_alsa_get_caps);
gst_element_add_pad (GST_ELEMENT (this), this->pad[0]);
- this->clock =
- gst_alsa_clock_new ("alsasrcclock", gst_alsa_src_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_element_set_loop_function (GST_ELEMENT (this), gst_alsa_src_loop);
}
+
static int
gst_alsa_src_mmap (GstAlsa * this, snd_pcm_sframes_t * avail)
{
@@ -359,26 +353,47 @@ gst_alsa_src_loop (GstElement * element)
src->buf[i] =
gst_buffer_new_and_alloc (gst_alsa_samples_to_bytes (this, avail));
}
+
/* fill buffer with data */
if ((copied = this->transmit (this, &avail)) <= 0)
return;
- /* push the buffers out and let them have fun */
- for (i = 0; i < element->numpads; i++) {
- GstBuffer *buf;
- if (!src->buf[i])
- return;
- if (copied != this->period_size)
- GST_BUFFER_SIZE (src->buf[i]) = gst_alsa_samples_to_bytes (this, copied);
- GST_BUFFER_TIMESTAMP (src->buf[i]) =
- gst_alsa_samples_to_timestamp (this, this->transmitted);
- GST_BUFFER_DURATION (src->buf[i]) =
- gst_alsa_samples_to_timestamp (this, copied);
- buf = src->buf[i];
- src->buf[i] = NULL;
- gst_pad_push (this->pad[i], GST_DATA (buf));
+ {
+ gint outsize;
+ GstClockTime outtime, outdur;
+
+ outsize = gst_alsa_samples_to_bytes (this, copied);
+ outdur = gst_alsa_samples_to_timestamp (this, copied);
+ outtime = GST_CLOCK_TIME_NONE;
+
+ if (GST_ELEMENT_CLOCK (this)) {
+ if (GST_CLOCK (GST_ALSA (this)->clock) == GST_ELEMENT_CLOCK (this)) {
+ outtime = gst_alsa_samples_to_timestamp (this, this->transmitted);
+ } else {
+ outtime = gst_element_get_time (GST_ELEMENT (this));
+ }
+ }
+
+ /* push the buffers out and let them have fun */
+ for (i = 0; i < element->numpads; i++) {
+ GstBuffer *buf;
+
+ if (!src->buf[i])
+ return;
+ if (copied != this->period_size)
+ GST_BUFFER_SIZE (src->buf[i]) = outsize;
+
+ GST_BUFFER_TIMESTAMP (src->buf[i]) = outtime;
+ GST_BUFFER_DURATION (src->buf[i]) = outdur;
+ GST_BUFFER_OFFSET (src->buf[i]) = this->transmitted;
+ GST_BUFFER_OFFSET_END (src->buf[i]) = this->transmitted + copied;
+
+ buf = src->buf[i];
+ src->buf[i] = NULL;
+ gst_pad_push (this->pad[i], GST_DATA (buf));
+ }
+ this->transmitted += copied;
}
- this->transmitted += copied;
}
static void
@@ -393,6 +408,7 @@ gst_alsa_src_flush (GstAlsaSrc * src)
}
}
}
+
static GstElementStateReturn
gst_alsa_src_change_state (GstElement * element)
{
@@ -404,7 +420,9 @@ gst_alsa_src_change_state (GstElement * element)
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
case GST_STATE_READY_TO_PAUSED:
+ break;
case GST_STATE_PAUSED_TO_PLAYING:
+ break;
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
@@ -421,15 +439,3 @@ gst_alsa_src_change_state (GstElement * element)
return GST_STATE_SUCCESS;
}
-
-static GstClockTime
-gst_alsa_src_get_time (GstAlsa * this)
-{
- snd_pcm_sframes_t delay;
-
- if (snd_pcm_delay (this->handle, &delay) == 0 && this->format) {
- return GST_SECOND * (this->transmitted + delay) / this->format->rate;
- } else {
- return 0;
- }
-}
diff --git a/ext/alsa/gstalsasrc.h b/ext/alsa/gstalsasrc.h
index 5b4c2b77f..d4e72e46a 100644
--- a/ext/alsa/gstalsasrc.h
+++ b/ext/alsa/gstalsasrc.h
@@ -38,6 +38,8 @@ typedef struct _GstAlsaSrcClass GstAlsaSrcClass;
struct _GstAlsaSrc {
GstAlsaMixer parent;
GstBuffer *buf[GST_ALSA_MAX_TRACKS];
+ snd_pcm_status_t *status;
+ GstClockTime base_time; /* FIXME: move this up ? already present in element ? */
};
struct _GstAlsaSrcClass {