diff --git a/ext/lame/gstlamemp3enc.c b/ext/lame/gstlamemp3enc.c
index c80ec8b..2ad9f9b 100644
--- a/ext/lame/gstlamemp3enc.c
+++ b/ext/lame/gstlamemp3enc.c
@@ -654,6 +654,21 @@ gst_lamemp3enc_get_property (GObject * object, guint prop_id, GValue * value,
   }
 }
 
+/* Returns duration of encoded mp3 stream with given length */
+static GstClockTime 
+get_encoded_duration(int mp3_size, GstLameMP3Enc *lame)
+{
+  /* duration of entire frame */
+  GstClockTime frame_duration = gst_util_uint64_scale_int(lame_get_framesize(lame->lgf), GST_SECOND, lame->samplerate);  
+  
+  /* Returns frame size multiplied by 1000 (to get around rounding errors in case the frame size is not really an integer
+   i.e. when rate is 44100 */
+  guint64 frame_size = gst_util_uint64_scale_int(144, lame->bitrate * 1000 * 1000, lame->samplerate);
+  
+  /** Compute the actual duration */
+  return gst_util_uint64_scale_int(mp3_size * 1000, frame_duration, frame_size);
+}
+
 static gboolean
 gst_lamemp3enc_sink_event (GstPad * pad, GstEvent * event)
 {
@@ -676,8 +691,7 @@ gst_lamemp3enc_sink_event (GstPad * pad, GstEvent * event)
         if (size > 0 && lame->last_flow == GST_FLOW_OK) {
           gint64 duration;
 
-          duration = gst_util_uint64_scale (size, 8 * GST_SECOND,
-              1000 * lame->bitrate);
+          duration = get_encoded_duration(size, lame);
 
           if (lame->last_ts == GST_CLOCK_TIME_NONE) {
             lame->last_ts = lame->eos_ts;
@@ -722,6 +736,8 @@ gst_lamemp3enc_sink_event (GstPad * pad, GstEvent * event)
         lame_encode_flush (lame->lgf, mp3_data, mp3_buffer_size);
         g_free (mp3_data);
       }
+      
+      lame->timestamp_offset = 0;
 
       ret = gst_pad_push_event (lame->srcpad, event);
       break;
@@ -755,11 +771,12 @@ gst_lamemp3enc_chain (GstPad * pad, GstBuffer * buf)
   GstLameMP3Enc *lame;
   guchar *mp3_data;
   gint mp3_buffer_size, mp3_size;
-  gint64 duration;
   GstFlowReturn result;
   gint num_samples;
   guint8 *data;
   guint size;
+  GstClockTime input_buffer_duration;
+  GstClockTime encoded_duration;
 
   lame = GST_LAMEMP3ENC (GST_PAD_PARENT (pad));
 
@@ -787,29 +804,38 @@ gst_lamemp3enc_chain (GstPad * pad, GstBuffer * buf)
         (short int *) data,
         num_samples / lame->num_channels, mp3_data, mp3_buffer_size);
   }
-
+  
+  /* get the actual duration of encoded data; this will be usually smaller than calculated duration
+     because lame keeps a buffer. */
+  encoded_duration = get_encoded_duration(mp3_size, lame);                                               
+  
   GST_LOG_OBJECT (lame, "encoded %d bytes of audio to %d bytes of mp3",
       size, mp3_size);
 
-  duration = gst_util_uint64_scale_int (size, GST_SECOND,
+  input_buffer_duration = gst_util_uint64_scale_int (size, GST_SECOND,
       2 * lame->samplerate * lame->num_channels);
 
   if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE &&
-      GST_BUFFER_DURATION (buf) != duration) {
+      GST_BUFFER_DURATION (buf) != input_buffer_duration) {
     GST_DEBUG_OBJECT (lame, "incoming buffer had incorrect duration %"
-        GST_TIME_FORMAT ", outgoing buffer will have correct duration %"
-        GST_TIME_FORMAT,
-        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_TIME_ARGS (duration));
+                      GST_TIME_FORMAT ", outgoing buffer will have correct duration %"
+                      GST_TIME_FORMAT,
+                      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_TIME_ARGS (input_buffer_duration));
   }
-
+  
   if (lame->last_ts == GST_CLOCK_TIME_NONE) {
-    lame->last_ts = GST_BUFFER_TIMESTAMP (buf);
+    lame->last_ts = GST_BUFFER_TIMESTAMP (buf) - lame->timestamp_offset;
     lame->last_offs = GST_BUFFER_OFFSET (buf);
-    lame->last_duration = duration;
+    lame->last_duration = encoded_duration;
   } else {
-    lame->last_duration += duration;
+    lame->last_duration += encoded_duration;
   }
 
+  /* Due to lame buffering the lame_encoder* method will likely return data encoded from input
+     that has been fed to it on previous iteration. The output timestamps need to be adjusted to
+     reflect this. */
+  lame->timestamp_offset = input_buffer_duration - encoded_duration + lame->timestamp_offset;;
+  
   gst_buffer_unref (buf);
 
   if (mp3_size < 0) {
@@ -951,6 +977,7 @@ gst_lamemp3enc_setup (GstLameMP3Enc * lame, GstTagList ** tags)
 
   if (lame->mono)
     CHECK_ERROR (lame_set_mode (lame->lgf, MONO));
+  
 
   /* initialize the lame encoder */
   if ((retval = lame_init_params (lame->lgf)) >= 0) {
diff --git a/ext/lame/gstlamemp3enc.h b/ext/lame/gstlamemp3enc.h
index 2ee8348..b437ed0 100644
--- a/ext/lame/gstlamemp3enc.h
+++ b/ext/lame/gstlamemp3enc.h
@@ -76,6 +76,8 @@ struct _GstLameMP3Enc {
 
   /* time tracker */
   guint64 last_ts, last_offs, last_duration, eos_ts;
+  
+  GstClockTime timestamp_offset;
 };
 
 struct _GstLameMP3EncClass {
