diff --git a/ext/alsa/gstalsasrc.c b/ext/alsa/gstalsasrc.c
index 20e6e15..e090956 100644
--- a/ext/alsa/gstalsasrc.c
+++ b/ext/alsa/gstalsasrc.c
@@ -73,7 +73,8 @@ static void gst_alsasrc_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
 static void gst_alsasrc_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
-
+static GstStateChangeReturn gst_alsasrc_change_state (GstElement * element,
+    GstStateChange transition);
 static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
 
 static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
@@ -81,7 +82,8 @@ static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
     GstAudioRingBufferSpec * spec);
 static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
 static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
-static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
+static guint gst_alsasrc_read
+  (GstAudioSrc * asrc, gpointer data, guint length, GstClockTime *timestamp);
 static guint gst_alsasrc_delay (GstAudioSrc * asrc);
 static void gst_alsasrc_reset (GstAudioSrc * asrc);
 
@@ -148,9 +150,10 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
   gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
   gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
   gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
-  gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
+  gstaudiosrc_class->timestamped_read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
   gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
   gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_alsasrc_change_state);
 
   g_object_class_install_property (gobject_class, PROP_DEVICE,
       g_param_spec_string ("device", "Device",
@@ -218,6 +221,41 @@ gst_alsasrc_get_property (GObject * object, guint prop_id,
   }
 }
 
+static GstStateChangeReturn
+gst_alsasrc_change_state (GstElement * element, GstStateChange transition)
+{
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+  GstAudioBaseSrc *src = GST_AUDIO_BASE_SRC (element);
+  GstAlsaSrc *alsa = GST_ALSA_SRC (element);
+  GstClock *clk;
+
+  switch (transition) {
+      /* Show the compiler that we care */
+    case GST_STATE_CHANGE_NULL_TO_READY:
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      clk = src->clock;
+      alsa->driver_timestamps = FALSE;
+      if (GST_IS_SYSTEM_CLOCK (clk)) {
+        gint clocktype;
+        g_object_get (clk, "clock-type", &clocktype, NULL);
+        if (clocktype == GST_CLOCK_TYPE_MONOTONIC) {
+          GST_INFO ("Using driver timestamps !");
+          alsa->driver_timestamps = TRUE;
+        }
+      }
+      break;
+  }
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  return ret;
+}
+
 static void
 gst_alsasrc_init (GstAlsaSrc * alsasrc)
 {
@@ -225,6 +263,7 @@ gst_alsasrc_init (GstAlsaSrc * alsasrc)
 
   alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
   alsasrc->cached_caps = NULL;
+  alsasrc->driver_timestamps = FALSE;
 
   alsasrc->alsa_lock = g_mutex_new ();
 }
@@ -451,6 +490,9 @@ set_swparams (GstAlsaSrc * alsa)
   /* start the transfer on first read */
   CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
           0), start_threshold);
+  /* Use monotonic timestamping */
+  CHECK (snd_pcm_sw_params_set_tstamp_mode (alsa->handle, params,
+          SND_PCM_TSTAMP_MMAP), tstamp_mode);
 
 #if GST_CHECK_ALSA_VERSION(1,0,16)
   /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
@@ -489,6 +531,13 @@ set_avail:
     snd_pcm_sw_params_free (params);
     return err;
   }
+tstamp_mode:
+  {
+    GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+        ("Unable to set tstamp mode for playback: %s", snd_strerror (err)));
+    snd_pcm_sw_params_free (params);
+    return err;
+  }
 #if !GST_CHECK_ALSA_VERSION(1,0,16)
 set_align:
   {
@@ -645,7 +694,7 @@ gst_alsasrc_open (GstAudioSrc * asrc)
   alsa = GST_ALSA_SRC (asrc);
 
   CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
-          SND_PCM_NONBLOCK), open_error);
+      (alsa->driver_timestamps == TRUE) ? 0 : SND_PCM_NONBLOCK), open_error);
 
   return TRUE;
 
@@ -781,8 +830,71 @@ xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err)
   return err;
 }
 
+static GstClockTime
+gst_alsasrc_get_timestamp (GstAlsaSrc * asrc)
+{
+  snd_pcm_status_t *status;
+  snd_htimestamp_t tstamp;
+  GstClockTime timestamp;
+  snd_pcm_uframes_t avail;
+  gint err = -EPIPE;
+  static GstClockTime last_ts = 0, orig_ts;
+
+  GST_LOG_OBJECT (asrc, "Getting alsa timestamp!");
+
+  if (G_UNLIKELY (!asrc)) {
+    GST_ERROR_OBJECT (asrc, "No alsa handle created yet !");
+    return 0;
+  }
+
+  if (G_UNLIKELY (snd_pcm_status_malloc (&status) != 0)) {
+    GST_ERROR_OBJECT (asrc, "snd_pcm_status_malloc failed");
+  }
+
+  if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
+    GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
+  }
+
+  /* In case an xrun condition has occured we need to handle this */
+  if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING) {
+    if (xrun_recovery (asrc, asrc->handle, err) < 0) {
+      GST_WARNING_OBJECT (asrc, "Could not recover from xrun condition !");
+    }
+    /* Reload the status alsa status object, since recovery made it invalid */
+    if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
+      GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
+    }
+  }
+
+  /* get high resolution time stamp from driver */
+  snd_pcm_status_get_htstamp (status, &tstamp);
+  orig_ts = timestamp = GST_TIMESPEC_TO_TIME (tstamp);
+
+  /* Max available frames sets the depth of the buffer */
+  avail =  snd_pcm_status_get_avail (status);
+
+  /* Calculate the timestamp of the next sample to be read */
+  timestamp -= gst_util_uint64_scale_int (avail, GST_SECOND, asrc->rate);
+
+  /* Compensate for the fact that we really need the timestamp of the
+   * previous read data segment (* 1000 to get period time in nanoseconds) */
+  timestamp -= asrc->period_time * 1000;
+
+  snd_pcm_status_free (status);
+
+  GST_LOG_OBJECT (asrc, "ALSA timestamp : %" GST_TIME_FORMAT
+		  ", Diff to previous %" GST_TIME_FORMAT ", delay %lu",
+		  GST_TIME_ARGS (timestamp),
+		  GST_TIME_ARGS (timestamp-last_ts),
+		  avail);
+
+  last_ts = timestamp;
+
+  return timestamp;
+}
+
 static guint
-gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
+gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length, GstClockTime *timestamp)
 {
   GstAlsaSrc *alsa;
   gint err;
@@ -811,6 +923,10 @@ gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
   }
   GST_ALSA_SRC_UNLOCK (asrc);
 
+  /* If driver timestamps are enabled we need to return this here */
+  if (alsa->driver_timestamps)
+    *timestamp = gst_alsasrc_get_timestamp (alsa);
+
   return length - (cptr * alsa->bpf);
 
 read_error:
diff --git a/gst-libs/gst/audio/gstaudioringbuffer.c b/gst-libs/gst/audio/gstaudioringbuffer.c
index 54fc5e4..9927cee 100644
--- a/gst-libs/gst/audio/gstaudioringbuffer.c
+++ b/gst-libs/gst/audio/gstaudioringbuffer.c
@@ -552,6 +552,9 @@ gst_audio_ring_buffer_acquire (GstAudioRingBuffer * buf,
   if (G_UNLIKELY (!res))
     goto acquire_failed;
 
+  GST_INFO_OBJECT (buf, "Allocating an array for %d timestamps", spec->segtotal);
+  buf->timestamps = g_slice_alloc0 (sizeof (GstClockTime) * spec->segtotal);
+
   if (G_UNLIKELY ((bpf = buf->spec.info.bpf) == 0))
     goto invalid_bpf;
 
@@ -1607,6 +1610,7 @@ gst_audio_ring_buffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
  * @sample: the sample position of the data
  * @data: where the data should be read
  * @len: the number of samples in data to read
+ * @timestamp: Where the timestamp is returned
  *
  * Read @len samples from the ringbuffer into the memory pointed 
  * to by @data.
@@ -1616,17 +1620,19 @@ gst_audio_ring_buffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
  * @len should not be a multiple of the segment size of the ringbuffer
  * although it is recommended.
  *
+ * @timestamp will return the timestamp associated with the data returned.
+ *
  * Returns: The number of samples read from the ringbuffer or -1 on
  * error.
  *
  * MT safe.
  */
 guint
-gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
-    guint8 * data, guint len)
+gst_audio_ring_buffer_timestamped_read (GstAudioRingBuffer * buf, guint64 sample, 
+    guchar * data, guint len, GstClockTime *timestamp)
 {
   gint segdone;
-  gint segsize, segtotal, channels, bps, bpf, sps;
+  gint segsize, segtotal, channels, bps, bpf, sps, readseg=0;
   guint8 *dest;
   guint to_read;
   gboolean need_reorder;
@@ -1648,7 +1654,7 @@ gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
   /* read enough samples */
   while (to_read > 0) {
     gint sampleslen;
-    gint readseg, sampleoff;
+    gint sampleoff;
 
     /* figure out the segment and the offset inside the segment where
      * the sample should be read from. */
@@ -1720,6 +1726,12 @@ gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample,
     data += sampleslen * bpf;
   }
 
+  if (buf->timestamps && timestamp) {
+    *timestamp = buf->timestamps[readseg % segtotal];
+    GST_INFO_OBJECT (buf, "Retrieved timestamp %" GST_TIME_FORMAT
+        " @ %d", GST_TIME_ARGS (*timestamp), readseg % segtotal);
+  }
+
   return len - to_read;
 
   /* ERRORS */
@@ -1731,6 +1743,33 @@ not_started:
 }
 
 /**
+ * gst_audio_ring_buffer_read:
+ * @buf: the #GsAudiotRingBuffer to read from
+ * @sample: the sample position of the data
+ * @data: where the data should be read
+ * @len: the number of samples in data to read
+ *
+ * Read @len samples from the ringbuffer into the memory pointed
+ * to by @data.
+ * The first sample should be read from position @sample in
+ * the ringbuffer.
+ *
+ * @len should not be a multiple of the segment size of the ringbuffer
+ * although it is recommended.
+ *
+ * Returns: The number of samples read from the ringbuffer or -1 on
+ * error.
+ *
+ * MT safe.
+ */
+guint
+gst_audio_ring_buffer_read (GstAudioRingBuffer * buf, guint64 sample, guchar * data,
+    guint len)
+{
+  return gst_audio_ring_buffer_timestamped_read (buf, sample, data, len, NULL);
+}
+
+/**
  * gst_audio_ring_buffer_prepare_read:
  * @buf: the #GstAudioRingBuffer to read from
  * @segment: the segment to read
@@ -1906,3 +1945,26 @@ gst_audio_ring_buffer_set_channel_positions (GstAudioRingBuffer * buf,
     }
   }
 }
+
+/**
+ * gst_ring_buffer_set_timestamp:
+ * @buf: the #GstRingBuffer
+ * @readseg: the current data segment
+ * @timestamp: The new timestamp of the buffer.
+ *
+ * Set a new timestamp on the buffer.
+ *
+ * MT safe.
+ *
+ * Since:
+ */
+void
+gst_audio_ring_buffer_set_timestamp(GstAudioRingBuffer * buf, gint readseg,
+    GstClockTime timestamp)
+{
+  g_return_if_fail (GST_IS_AUDIO_RING_BUFFER (buf));
+
+  GST_INFO_OBJECT (buf, "Storing timestamp %" GST_TIME_FORMAT
+      " @ %d", GST_TIME_ARGS (timestamp), readseg);
+  buf->timestamps[readseg] = timestamp;
+}
diff --git a/gst-libs/gst/audio/gstaudioringbuffer.h b/gst-libs/gst/audio/gstaudioringbuffer.h
index 8bf6bfd..9dc2114 100644
--- a/gst-libs/gst/audio/gstaudioringbuffer.h
+++ b/gst-libs/gst/audio/gstaudioringbuffer.h
@@ -176,6 +176,7 @@ struct _GstAudioRingBuffer {
   gboolean                    acquired;
   guint8                     *memory;
   gsize                       size;
+  GstClockTime               *timestamps;
   GstAudioRingBufferSpec      spec;
   gint                        samples_per_seg;
   guint8                     *empty_seg;
@@ -200,7 +201,7 @@ struct _GstAudioRingBuffer {
   gboolean                    active;
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING-1];
 };
 
 /**
@@ -310,6 +311,12 @@ guint           gst_audio_ring_buffer_commit          (GstAudioRingBuffer * buf,
 /* read samples */
 guint           gst_audio_ring_buffer_read            (GstAudioRingBuffer *buf, guint64 sample,
                                                        guint8 *data, guint len);
+guint           gst_audio_ring_buffer_timestamped_read(GstAudioRingBuffer *buf, guint64 sample,
+                                                       guchar *data, guint len, GstClockTime *timestamp);
+
+/* Set timestamp on buffer */
+void            gst_audio_ring_buffer_set_timestamp   (GstAudioRingBuffer * buf, gint readseg, GstClockTime 
+                                                       timestamp);
 
 /* mostly protected */
 /* not yet implemented
diff --git a/gst-libs/gst/audio/gstaudiosrc.c b/gst-libs/gst/audio/gstaudiosrc.c
index a09cf87..bc0f017 100644
--- a/gst-libs/gst/audio/gstaudiosrc.c
+++ b/gst-libs/gst/audio/gstaudiosrc.c
@@ -192,7 +192,8 @@ gst_audio_src_ring_buffer_class_init (GstAudioSrcRingBufferClass * klass)
       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_delay);
 }
 
-typedef guint (*ReadFunc) (GstAudioSrc * src, gpointer data, guint length);
+typedef guint (*ReadFunc)
+  (GstAudioSrc * src, gpointer data, guint length, GstClockTime *timestamp);
 
 /* this internal thread does nothing else but read samples from the audio device.
  * It will read each segment in the ringbuffer and will update the play
@@ -214,7 +215,7 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
 
   GST_DEBUG_OBJECT (src, "enter thread");
 
-  readfunc = csrc->read;
+  readfunc = csrc->timestamped_read;
   if (readfunc == NULL)
     goto no_function;
 
@@ -231,13 +232,14 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
     gint left, len;
     guint8 *readptr;
     gint readseg;
+    GstClockTime timestamp = 0;
 
     if (gst_audio_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
       gint read;
 
       left = len;
       do {
-        read = readfunc (src, readptr, left);
+        read = readfunc (src, readptr, left, &timestamp);
         GST_LOG_OBJECT (src, "transfered %d bytes of %d to segment %d", read,
             left, readseg);
         if (read < 0 || read > left) {
@@ -250,6 +252,10 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
         readptr += read;
       } while (left > 0);
 
+      /* Update timestamp on buffer if required */
+      if (timestamp)
+        gst_audio_ring_buffer_set_timestamp (buf, readseg, timestamp);
+
       /* we read one segment */
       gst_audio_ring_buffer_advance (buf, 1);
     } else {
diff --git a/gst-libs/gst/audio/gstaudiosrc.h b/gst-libs/gst/audio/gstaudiosrc.h
index 362411e..508a595 100644
--- a/gst-libs/gst/audio/gstaudiosrc.h
+++ b/gst-libs/gst/audio/gstaudiosrc.h
@@ -82,13 +82,16 @@ struct _GstAudioSrcClass {
   gboolean (*close)     (GstAudioSrc *src);
   /* read samples from the device */
   guint    (*read)      (GstAudioSrc *src, gpointer data, guint length);
+  /* read samples from the device, return timestamp if required */
+  guint    (*timestamped_read) (GstAudioSrc *src, gpointer data, guint length,
+      GstClockTime *timestamp);
   /* get number of samples queued in the device */
   guint    (*delay)     (GstAudioSrc *src);
   /* reset the audio device, unblock from a write */
   void     (*reset)     (GstAudioSrc *src);
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING-1];
 };
 
 GType gst_audio_src_get_type(void);
