diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2004-06-17 14:10:21 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2004-06-17 14:10:21 +0000 |
commit | a48818210de4cef95e9a30503ba7bb04f0f3a9ac (patch) | |
tree | a6aaa2022939eb4535065ceecf44ae7e12985094 | |
parent | 7face56b420df8de21a33ee57345188b1a0cee3c (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-- | ChangeLog | 13 | ||||
-rw-r--r-- | ext/alsa/gstalsa.c | 40 | ||||
-rw-r--r-- | ext/alsa/gstalsa.h | 3 | ||||
-rw-r--r-- | ext/alsa/gstalsasrc.c | 76 | ||||
-rw-r--r-- | ext/alsa/gstalsasrc.h | 2 |
5 files changed, 99 insertions, 35 deletions
@@ -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, ×tamp); + + /* 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 { |