diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c
index fc1582b..5e57d44 100644
--- a/libs/gst/base/gstadapter.c
+++ b/libs/gst/base/gstadapter.c
@@ -142,6 +142,8 @@ struct _GstAdapter
   guint64 pts_distance;
   GstClockTime dts;
   guint64 dts_distance;
+  GstClockTime dur;
+  guint64 dur_distance;
 
   gsize scan_offset;
   GSList *scan_entry;
@@ -180,6 +182,8 @@ gst_adapter_init (GstAdapter * adapter)
   adapter->pts_distance = 0;
   adapter->dts = GST_CLOCK_TIME_NONE;
   adapter->dts_distance = 0;
+  adapter->dur = GST_CLOCK_TIME_NONE;
+  adapter->dur_distance = 0;
 }
 
 static void
@@ -240,6 +244,8 @@ gst_adapter_clear (GstAdapter * adapter)
   adapter->pts_distance = 0;
   adapter->dts = GST_CLOCK_TIME_NONE;
   adapter->dts_distance = 0;
+  adapter->dur = GST_CLOCK_TIME_NONE;
+  adapter->dur_distance = 0;
   adapter->scan_offset = 0;
   adapter->scan_entry = NULL;
 }
@@ -247,7 +253,7 @@ gst_adapter_clear (GstAdapter * adapter)
 static inline void
 update_timestamps (GstAdapter * adapter, GstBuffer * buf)
 {
-  GstClockTime pts, dts;
+  GstClockTime pts, dts, dur;
 
   pts = GST_BUFFER_PTS (buf);
   if (GST_CLOCK_TIME_IS_VALID (pts)) {
@@ -261,6 +267,12 @@ update_timestamps (GstAdapter * adapter, GstBuffer * buf)
     adapter->dts = dts;
     adapter->dts_distance = 0;
   }
+  dur = GST_BUFFER_DURATION (buf);
+  if (GST_CLOCK_TIME_IS_VALID (dur)) {
+    GST_LOG_OBJECT (adapter, "new duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
+    adapter->dur = dts;
+    adapter->dur_distance = 0;
+  }
 }
 
 /* copy data into @dest, skipping @skip bytes from the head buffers */
@@ -596,6 +608,7 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
   /* distance is always at least the amount of skipped bytes */
   adapter->pts_distance -= adapter->skip;
   adapter->dts_distance -= adapter->skip;
+  adapter->dur_distance -= adapter->skip;
 
   g = adapter->buflist;
   cur = g->data;
@@ -605,6 +618,7 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
     GST_LOG_OBJECT (adapter, "flushing out head buffer");
     adapter->pts_distance += size;
     adapter->dts_distance += size;
+    adapter->dur_distance += size;
     flush -= size;
 
     gst_buffer_unref (cur);
@@ -625,6 +639,7 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
   adapter->skip = flush;
   adapter->pts_distance += flush;
   adapter->dts_distance += flush;
+  adapter->dur_distance += flush;
   /* invalidate scan position */
   adapter->scan_offset = 0;
   adapter->scan_entry = NULL;
@@ -1158,6 +1173,82 @@ gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset,
 }
 
 /**
+ * gst_adapter_prev_duration:
+ * @adapter: a #GstAdapter
+ * @distance: (out) (allow-none): pointer to location for distance, or %NULL
+ *
+ * Get the duration that was before the current byte in the adapter. When
+ * @distance is given, the amount of bytes between the buffer and the current
+ * position is returned.
+ *
+ * The duration is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
+ * the adapter is first created or when it is cleared. This also means that before
+ * the first byte with a duration is removed from the adapter, the duration
+ * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
+ *
+ * Since: 1.6
+ * Returns: The previously seen duration.
+ */
+GstClockTime
+gst_adapter_prev_duration (GstAdapter * adapter, guint64 * distance)
+{
+  g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
+
+  if (distance)
+    *distance = adapter->dur_distance;
+
+  return adapter->dur;
+}
+
+/**
+ * gst_adapter_prev_duration_at_offset:
+ * @adapter: a #GstAdapter
+ * @offset: the offset in the adapter at which to get buffer's duration
+ * @distance: (out) (allow-none): pointer to location for distance, or %NULL
+ *
+ * Get the duration that was before the byte at offset @offset in the adapter. When
+ * @distance is given, the amount of bytes between the buffer and the current
+ * position is returned.
+ *
+ * The duration is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
+ * the adapter is first created or when it is cleared. This also means that before
+ * the first byte with a duration is removed from the adapter, the duration
+ * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
+ *
+ * Since: 1.6
+ * Returns: The previously seen duration at given offset.
+ */
+GstClockTime
+gst_adapter_prev_duration_at_offset (GstAdapter * adapter, gsize offset,
+    guint64 * distance)
+{
+  GstBuffer *cur;
+  GSList *g;
+  gsize read_offset = 0;
+  GstClockTime dur = adapter->dur;
+
+  g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
+
+  g = adapter->buflist;
+
+  while (g && read_offset < offset + adapter->skip) {
+    cur = g->data;
+
+    read_offset += gst_buffer_get_size (cur);
+    if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (cur))) {
+      dur = GST_BUFFER_DURATION (cur);
+    }
+
+    g = g_slist_next (g);
+  }
+
+  if (distance)
+    *distance = adapter->dur_distance + offset;
+
+  return dur;
+}
+
+/**
  * gst_adapter_masked_scan_uint32_peek:
  * @adapter: a #GstAdapter
  * @mask: mask to apply to data before matching against @pattern
diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h
index f82fbfb..98d7be2 100644
--- a/libs/gst/base/gstadapter.h
+++ b/libs/gst/base/gstadapter.h
@@ -71,6 +71,9 @@ GstClockTime            gst_adapter_prev_dts            (GstAdapter *adapter, gu
 GstClockTime            gst_adapter_prev_pts_at_offset  (GstAdapter * adapter, gsize offset, guint64 * distance);
 GstClockTime            gst_adapter_prev_dts_at_offset  (GstAdapter * adapter, gsize offset, guint64 * distance);
 
+GstClockTime            gst_adapter_prev_duration           (GstAdapter *adapter, guint64 *distance);
+GstClockTime            gst_adapter_prev_duration_at_offset (GstAdapter * adapter, gsize offset, guint64 * distance);
+
 gssize                  gst_adapter_masked_scan_uint32  (GstAdapter * adapter, guint32 mask,
                                                          guint32 pattern, gsize offset, gsize size);
 
diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c
index 57e78bb..1b842fa 100644
--- a/libs/gst/base/gstbaseparse.c
+++ b/libs/gst/base/gstbaseparse.c
@@ -2727,7 +2727,7 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   gint skip = -1;
   const guint8 *data;
   guint min_size, av;
-  GstClockTime pts, dts;
+  GstClockTime pts, dts, dur;
 
   parse = GST_BASE_PARSE (parent);
   bclass = GST_BASE_PARSE_GET_CLASS (parse);
@@ -2865,6 +2865,7 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
      * but interpolate in between */
     pts = gst_adapter_prev_pts (parse->priv->adapter, NULL);
     dts = gst_adapter_prev_dts (parse->priv->adapter, NULL);
+    dur = gst_adapter_prev_duration (parse->priv->adapter, NULL);
     if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts))
       parse->priv->prev_pts = parse->priv->next_pts = pts;
 
@@ -2893,6 +2894,7 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
     if (parse->priv->upstream_format == GST_FORMAT_TIME) {
       GST_BUFFER_PTS (tmpbuf) = parse->priv->next_pts;
       GST_BUFFER_DTS (tmpbuf) = parse->priv->next_dts;
+      GST_BUFFER_DURATION (tmpbuf) = dur;
     }
 
     /* keep the adapter mapped, so keep track of what has to be flushed */
