diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c
index 9328f9c..c999cb9 100644
--- a/gst/mpegtsmux/mpegtsmux.c
+++ b/gst/mpegtsmux/mpegtsmux.c
@@ -150,8 +150,46 @@ static GstStateChangeReturn mpegtsmux_change_state (GstElement * element,
     GstStateChange transition);
 static void mpegtsdemux_set_header_on_caps (MpegTsMux * mux);
 
+static void mpegtsmux_set_index (GstElement * element, GstIndex * index);
+static GstIndex *mpegtsmux_get_index (GstElement * element);
+
+static GstFormat pts_format;
+static GstFormat spn_format;
+
 GST_BOILERPLATE (MpegTsMux, mpegtsmux, GstElement, GST_TYPE_ELEMENT);
 
+
+static void
+mpegtsmux_set_index (GstElement * element, GstIndex * index)
+{
+  MpegTsMux *mux = GST_MPEG_TSMUX (element);
+
+  GST_OBJECT_LOCK (mux);
+  if (mux->element_index)
+    gst_object_unref (mux->element_index);
+  mux->element_index = index ? gst_object_ref (index) : NULL;
+  GST_OBJECT_UNLOCK (mux);
+  GST_INFO_OBJECT (mux, "Set index %" GST_PTR_FORMAT, mux->element_index);
+  gst_index_add_format (index, mux->element_index_writer_id, pts_format);
+  gst_index_add_format (index, mux->element_index_writer_id, spn_format);
+}
+
+static GstIndex *
+mpegtsmux_get_index (GstElement * element)
+{
+  GstIndex *result = NULL;
+  MpegTsMux *mux = GST_MPEG_TSMUX (element);
+
+  GST_OBJECT_LOCK (mux);
+  if (mux->element_index)
+    result = gst_object_ref (mux->element_index);
+  GST_OBJECT_UNLOCK (mux);
+
+  GST_DEBUG_OBJECT (mux, "Returning index %" GST_PTR_FORMAT, result);
+
+  return result;
+}
+
 static void
 mpegtsmux_base_init (gpointer g_class)
 {
@@ -167,6 +205,10 @@ mpegtsmux_base_init (gpointer g_class)
       "MPEG Transport Stream Muxer", "Codec/Muxer",
       "Multiplexes media streams into an MPEG Transport Stream",
       "Fluendo <contact@fluendo.com>");
+
+  pts_format =
+      gst_format_register ("PTS", "MPEG System Presentation Time Stamp");
+  spn_format = gst_format_register ("SPN", "Source Packet Number");
 }
 
 static void
@@ -183,6 +225,9 @@ mpegtsmux_class_init (MpegTsMuxClass * klass)
   gstelement_class->release_pad = mpegtsmux_release_pad;
   gstelement_class->change_state = mpegtsmux_change_state;
 
+  gstelement_class->set_index = GST_DEBUG_FUNCPTR (mpegtsmux_set_index);
+  gstelement_class->get_index = GST_DEBUG_FUNCPTR (mpegtsmux_get_index);
+
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PROG_MAP,
       g_param_spec_boxed ("prog-map", "Program map",
           "A GstStructure specifies the mapping from elementary streams to programs",
@@ -236,6 +281,9 @@ mpegtsmux_init (MpegTsMux * mux, MpegTsMuxClass * g_class)
   mux->prog_map = NULL;
   mux->streamheader = NULL;
   mux->streamheader_sent = FALSE;
+
+  mux->element_index = NULL;
+  mux->element_index_writer_id = -1;
 }
 
 static void
@@ -277,6 +325,9 @@ mpegtsmux_dispose (GObject * object)
     g_list_free (mux->streamheader);
     mux->streamheader = NULL;
   }
+  if (mux->element_index)
+    gst_object_unref (mux->element_index);
+
   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
 }
 
@@ -494,6 +545,15 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data, GstPad * pad)
     ret = GST_FLOW_OK;
   }
 
+  if (mux->element_index) {
+    if (mux->element_index_writer_id == -1) {
+      gst_index_get_writer_id (mux->element_index, GST_OBJECT (mux),
+          &mux->element_index_writer_id);
+      GST_INFO_OBJECT (mux, "created GstIndex writer_id = %d",
+          mux->element_index_writer_id);
+    }
+  }
+
 beach:
   gst_caps_unref (caps);
   return ret;
@@ -815,6 +875,10 @@ new_packet_cb (guint8 * data, guint len, void *user_data, gint64 new_pcr)
   gfloat current_ts;
   gint64 m2ts_pcr, pcr_bytes, chunk_bytes;
   gint64 ts_rate;
+  static guint64 spn_count = 0;
+  guint64 pts;
+  unsigned char packet[M2TS_PACKET_LENGTH];
+  unsigned char *pkt;
 
   if (mux->m2ts_mode == TRUE) {
     /* Enters when the m2ts-mode is set true */
@@ -866,17 +930,20 @@ new_packet_cb (guint8 * data, guint len, void *user_data, gint64 new_pcr)
              m2ts packets and pushed */
           current_ts = ((gfloat) mux->previous_pcr / STANDARD_TIME_CLOCK) +
               ((gfloat) pcr_bytes / ts_rate);
-          m2ts_pcr = (((gint64) (STANDARD_TIME_CLOCK * current_ts / 300) &
-                  TWO_POW_33_MINUS1) * 300) + ((gint64) (STANDARD_TIME_CLOCK *
-                  current_ts) % 300);
+          m2ts_pcr = ((((gint64) (STANDARD_TIME_CLOCK * current_ts / 300) &
+                      TWO_POW_33_MINUS1) * 300) +
+              ((gint64) (STANDARD_TIME_CLOCK * current_ts) % 300));
 
           out_buf = gst_adapter_take_buffer (mux->adapter, M2TS_PACKET_LENGTH);
+
           if (G_UNLIKELY (!out_buf))
             break;
+
           gst_buffer_set_caps (out_buf, GST_PAD_CAPS (mux->srcpad));
 
           /*writing the 4  byte timestamp value */
-          GST_WRITE_UINT32_BE (GST_BUFFER_DATA (out_buf), m2ts_pcr);
+          GST_WRITE_UINT32_BE (GST_BUFFER_DATA (out_buf),
+              m2ts_pcr & 0x3FFFFFFF);
 
           GST_LOG_OBJECT (mux, "Outputting a packet of length %d",
               M2TS_PACKET_LENGTH);
@@ -885,7 +952,55 @@ new_packet_cb (guint8 * data, guint len, void *user_data, gint64 new_pcr)
             mux->last_flow_ret = ret;
             return FALSE;
           }
+
           pcr_bytes += M2TS_PACKET_LENGTH;
+
+          spn_count++;
+          if (mux->element_index) {
+            memcpy (packet, GST_BUFFER_DATA (out_buf), M2TS_PACKET_LENGTH);
+            pkt = packet + 4;
+
+            if (!!(pkt[1] & 0x40))          /* payload unit start indicator flag? */
+            {
+              GST_LOG_OBJECT (mux, "pusi found for pid 0x%02X%02X",
+                  pkt[1] & 0x1F, pkt[2]);
+              if ((pkt[3] & 0x10)) {        /* no payload? */
+                if (pkt[3] & 0x20)          /* adaptation field present? */
+                  pkt += pkt[4] + 4 + 1;    /* skip adaptation field and header */
+                else
+                  pkt += 4;                 /* skip header */
+
+                if (pkt <= packet + M2TS_PACKET_LENGTH) {
+                  if (pkt[0] == 0 && pkt[1] == 0 && pkt[2] == 1) {
+                    if (pkt[7] & 0x80)      /* PTS present? */
+                    {
+                      pts = ((guint64) (pkt[9] & 0xE)) << 29;
+                      pts |= ((guint64) (pkt[10] & 0xFF)) << 22;
+                      pts |= ((guint64) (pkt[11] & 0xFE)) << 14;
+                      pts |= ((guint64) (pkt[12] & 0xFF)) << 7;
+                      pts |= ((guint64) (pkt[13] & 0xFE)) >> 1;
+                      GST_LOG_OBJECT (mux, "PTS present: %" G_GUINT64_FORMAT,
+                          pts);
+
+                      pkt += pkt[8] + 10;   /* advance to payload v*/
+                      if (!(pkt[0] || pkt[1] || (pkt[2] != 1))) {
+                        if (pkt[3] == 0x09 &&   /* MPEG4 AVC NAL unit access delimiter */
+                            (pkt[4] >> 5) == 0) {       /* and I-frame */
+                          gst_index_add_association (mux->element_index,
+                              mux->element_index_writer_id,
+                              GST_ASSOCIATION_FLAG_KEY_UNIT, spn_format,
+                              spn_count, pts_format, pts, NULL);
+                        }
+                      }
+                    }
+                  } else
+                    GST_LOG_OBJECT (mux, "no valid startcode");
+                } else
+                  GST_DEBUG_OBJECT (mux, "adaption field too long");
+              } else
+                GST_DEBUG_OBJECT (mux, "no payload");
+            }
+          }
         }
         mux->previous_pcr = m2ts_pcr;
       }
@@ -946,10 +1061,10 @@ mpegtsdemux_set_header_on_caps (MpegTsMux * mux)
   GstStructure *structure;
   GValue array = { 0 };
   GValue value = { 0 };
-  GstCaps *caps;
+  GstCaps *caps = GST_PAD_CAPS (mux->srcpad);
   GList *sh;
 
-  caps = gst_caps_copy (GST_PAD_CAPS (mux->srcpad));
+  caps = gst_caps_make_writable (caps);
   structure = gst_caps_get_structure (caps, 0);
 
   g_value_init (&array, GST_TYPE_ARRAY);
