commit 437b87b4c030d9083de17351fad02bcbd227a4b2
Author: Stas Sergeev <stas@stas.(none)>
Date:   Thu Aug 25 19:32:38 2011 +0400

    add PES payloader, depayloader and parser plugins

diff --git a/configure.ac b/configure.ac
index 3450bd2..47ded98 100644
--- a/configure.ac
+++ b/configure.ac
@@ -333,6 +333,7 @@ AG_GST_CHECK_PLUGIN(liveadder)
 AG_GST_CHECK_PLUGIN(mpegdemux)
 AG_GST_CHECK_PLUGIN(mpegtsdemux)
 AG_GST_CHECK_PLUGIN(mpegtsmux)
+AG_GST_CHECK_PLUGIN(mpegpes)
 AG_GST_CHECK_PLUGIN(mpegpsmux)
 AG_GST_CHECK_PLUGIN(mpeg4videoparse)
 AG_GST_CHECK_PLUGIN(mpegvideoparse)
@@ -1910,6 +1911,7 @@ gst/mpegdemux/Makefile
 gst/mpegtsdemux/Makefile
 gst/mpegtsmux/Makefile
 gst/mpegtsmux/tsmux/Makefile
+gst/mpegpes/Makefile
 gst/mpegpsmux/Makefile
 gst/mpeg4videoparse/Makefile
 gst/mpegvideoparse/Makefile
diff --git a/gst/mpegpes/Makefile.am b/gst/mpegpes/Makefile.am
new file mode 100644
index 0000000..dab594b
--- /dev/null
+++ b/gst/mpegpes/Makefile.am
@@ -0,0 +1,44 @@
+plugin_LTLIBRARIES = libgstmpegpespay.la libgstmpegpesdepay.la \
+	libgstmpegpesparse.la
+
+libgstmpegpespay_la_SOURCES = \
+	mpegpespay.c \
+	tsmuxstream.c \
+	mpegtsmux_h264.c \
+	mpegtsmux_aac.c
+
+libgstmpegpespay_la_CFLAGS = $(GST_CFLAGS)
+libgstmpegpespay_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstmpegpespay_la_LIBTOOLFLAGS = --tag=disable-static
+
+libgstmpegpesdepay_la_SOURCES = \
+	mpegpesdepay.c \
+	mpegpescmn.c \
+	pesparse.c
+
+libgstmpegpesdepay_la_CFLAGS = $(GST_CFLAGS)
+libgstmpegpesdepay_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstmpegpesdepay_la_LIBADD = $(GST_BASE_LIBS)
+libgstmpegpesdepay_la_LIBTOOLFLAGS = --tag=disable-static
+
+libgstmpegpesparse_la_SOURCES = \
+	mpegpesparse.c \
+	mpegpescmn.c \
+	pesparse.c
+
+libgstmpegpesparse_la_CFLAGS = $(GST_CFLAGS)
+libgstmpegpesparse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstmpegpesparse_la_LIBADD = $(GST_BASE_LIBS)
+libgstmpegpesparse_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = \
+	mpegpespay.h \
+	mpegpesdepay.h \
+	mpegpesparse.h \
+	mpegpescmn.h \
+	tsmuxstream.h \
+	tsmuxcommon.h \
+	mpegtsmux_h264.h \
+	mpegtsmux_aac.h \
+	pesparse.h \
+	gstmpegdefs.h
diff --git a/gst/mpegpes/gstmpegdefs.h b/gst/mpegpes/gstmpegdefs.h
new file mode 100644
index 0000000..be6209a
--- /dev/null
+++ b/gst/mpegpes/gstmpegdefs.h
@@ -0,0 +1,226 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Fluendo MPEG Demuxer plugin.
+ *
+ * The Initial Developer of the Original Code is Fluendo, S.L.
+ * Portions created by Fluendo, S.L. are Copyright (C) 2005
+ * Fluendo, S.L. All Rights Reserved.
+ *
+ * Contributor(s): Wim Taymans <wim@fluendo.com>
+ */
+
+#ifndef __GST_MPEG_DEFS_H__
+#define __GST_MPEG_DEFS_H__
+
+/*
+ * 1011 1100                program_stream_map
+ * 1011 1101                private_stream_1
+ * 1011 1110                padding_stream
+ * 1011 1111                private_stream_2
+ * 110x xxxx                ISO/IEC 13818-3 or ISO/IEC 11172-3 audio stream number x xxxx
+ * 1110 xxxx                ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 video stream number xxxx
+ * 1111 0000                ECM_stream
+ * 1111 0001                EMM_stream
+ * 1111 0010                ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A or ISO/IEC 13818-6_DSMCC_stream
+ * 1111 0011                ISO/IEC_13522_stream
+ * 1111 0100                ITU-T Rec. H.222.1 type A
+ * 1111 0101                ITU-T Rec. H.222.1 type B
+ * 1111 0110                ITU-T Rec. H.222.1 type C
+ * 1111 0111                ITU-T Rec. H.222.1 type D
+ * 1111 1000                ITU-T Rec. H.222.1 type E
+ * 1111 1001                ancillary_stream
+ * 1111 1010                ISO/IEC 14496-1_SL-packetized_stream
+ * 1111 1011                ISO/IEC 14496-1_FlexMux_stream
+ * 1111 1100                metadata stream
+ * 1111 1101                extended_stream_id
+ * 1111 1110                reserved data stream
+ * 1111 1111                program_stream_directory
+ */
+
+#define ID_PS_END_CODE                          0x000001B9
+#define ID_PS_PACK_START_CODE                   0x000001BA
+#define ID_PS_SYSTEM_HEADER_START_CODE          0x000001BB
+#define ID_PS_PROGRAM_STREAM_MAP                0x000001BC
+#define ID_PRIVATE_STREAM_1                     0x000001BD
+#define ID_PADDING_STREAM                       0x000001BE
+#define ID_PRIVATE_STREAM_2                     0x000001BF
+#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_0        0x000001C0
+#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_32       0x000001DF
+#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_0        0x000001E0
+#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_16       0x000001EF
+#define ID_ECM_STREAM                           0x000001F0
+#define ID_EMM_STREAM                           0x000001F1
+#define ID_DSMCC_STREAM                         0x000001F2
+#define ID_ISO_IEC_13522_STREAM                 0x000001F3
+#define ID_ITU_TREC_H222_TYPE_A_STREAM          0x000001F4
+#define ID_ITU_TREC_H222_TYPE_B_STREAM          0x000001F5
+#define ID_ITU_TREC_H222_TYPE_C_STREAM          0x000001F6
+#define ID_ITU_TREC_H222_TYPE_D_STREAM          0x000001F7
+#define ID_ITU_TREC_H222_TYPE_E_STREAM          0x000001F8
+#define ID_ANCILLARY_STREAM                     0x000001F9
+#define ID_14496_1_SL_PACKETIZED_STREAM         0x000001FA
+#define ID_14496_1_SL_FLEXMUX_STREAM            0x000001FB
+#define ID_METADATA_STREAM                      0x000001FC
+#define ID_EXTENDED_STREAM_ID                   0x000001FD
+#define ID_RESERVED_STREAM_3                    0x000001FE
+#define ID_PROGRAM_STREAM_DIRECTORY             0x000001FF
+
+#define PACKET_VIDEO_START_CODE                 0x000001E0
+#define PACKET_AUDIO_START_CODE                 0x000001C0
+#define PICTURE_START_CODE                      0x00000100
+#define USER_DATA_START_CODE                    0x000001B2
+#define SEQUENCE_HEADER_CODE                    0x000001B3
+#define SEQUENCE_ERROR_CODE                     0x000001B4
+#define EXTENSION_START_CODE                    0x000001B5
+#define SEQUENCE_END_CODE                       0x000001B7
+#define GROUP_START_CODE                        0x000001B8
+
+#define AC3_SYNC_WORD                           0x0b770000
+
+#define MPEG_TS_SYNC_BYTE                       0x00000047
+
+#define PID_PROGRAM_ASSOCIATION_TABLE          0x0000
+#define PID_CONDITIONAL_ACCESS_TABLE           0x0001
+#define PID_RESERVED_FIRST                     0x0002
+#define PID_RESERVED_LAST                      0x0010
+#define PID_NULL_PACKET                        0x1FFF
+
+#define PID_TYPE_UNKNOWN                        0
+#define PID_TYPE_RESERVED                       1
+#define PID_TYPE_PROGRAM_ASSOCIATION            2
+#define PID_TYPE_CONDITIONAL_ACCESS             3
+#define PID_TYPE_PROGRAM_MAP                    4
+#define PID_TYPE_ELEMENTARY                     5
+#define PID_TYPE_NULL_PACKET                    6
+#define PID_TYPE_PRIVATE_SECTION                7
+
+/* Stream type assignments
+ * 
+ *   0x00    ITU-T | ISO/IEC Reserved
+ *   0x01    ISO/IEC 11172 Video
+ *   0x02    ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or
+ *           ISO/IEC 11172-2 constrained parameter video
+ *           stream
+ *   0x03    ISO/IEC 11172 Audio
+ *   0x04    ISO/IEC 13818-3 Audio
+ *   0x05    ITU-T Rec. H.222.0 | ISO/IEC 13818-1
+ *           private_sections
+ *   0x06    ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES
+ *           packets containing private data
+ *   0x07    ISO/IEC 13522 MHEG
+ *   0x08    ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A
+ *           DSM CC
+ *   0x09    ITU-T Rec. H.222.1
+ *   0x0A    ISO/IEC 13818-6 type A
+ *   0x0B    ISO/IEC 13818-6 type B
+ *   0x0C    ISO/IEC 13818-6 type C
+ *   0x0D    ISO/IEC 13818-6 type D
+ *   0x0E    ISO/IEC 13818-1 auxiliary
+ * 0x0F-0x7F ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved
+ * 0x80-0xFF User Private
+ */
+#define ST_RESERVED                     0x00
+#define ST_VIDEO_MPEG1                  0x01
+#define ST_VIDEO_MPEG2                  0x02
+#define ST_AUDIO_MPEG1                  0x03
+#define ST_AUDIO_MPEG2                  0x04
+#define ST_PRIVATE_SECTIONS             0x05
+#define ST_PRIVATE_DATA                 0x06
+#define ST_MHEG                         0x07
+#define ST_DSMCC                        0x08
+#define ST_H222_1                       0x09
+
+#define ST_DSMCC_A                      0x0a
+#define ST_DSMCC_B                      0x0b
+#define ST_DSMCC_C                      0x0c
+#define ST_DSMCC_D                      0x0d
+
+/* later extensions */
+#define ST_AUDIO_AAC                    0x0f
+#define ST_VIDEO_MPEG4                  0x10
+#define ST_VIDEO_H264                   0x1b
+
+/* Un-official Dirac extension */
+#define ST_VIDEO_DIRAC                  0xd1
+
+/* private stream types */
+#define ST_PS_AUDIO_AC3                 0x81
+#define ST_PS_AUDIO_DTS                 0x8a
+#define ST_PS_AUDIO_LPCM                0x8b
+#define ST_PS_DVD_SUBPICTURE            0xff
+/* Blu-ray related */
+#define ST_BD_AUDIO_LPCM                0x80
+#define ST_BD_AUDIO_AC3                 0x81
+#define ST_BD_AUDIO_DTS                 0x82
+#define ST_BD_AUDIO_AC3_TRUE_HD         0x83
+#define ST_BD_AUDIO_AC3_PLUS            0x84
+#define ST_BD_AUDIO_DTS_HD              0x85
+#define ST_BD_AUDIO_DTS_HD_MASTER_AUDIO 0x86
+#define ST_BD_AUDIO_EAC3                0x87
+#define ST_BD_PGS_SUBPICTURE            0x90
+#define ST_BD_IGS                       0x91
+#define ST_BD_SUBTITLE                  0x92
+#define ST_BD_SECONDARY_AC3_PLUS        0xa1
+#define ST_BD_SECONDARY_DTS_HD          0xa2
+
+/* defined for VC1 extension in RP227 */
+#define ST_PRIVATE_EA                   0xea
+
+/* HDV AUX stream mapping
+ * 0xA0      ISO/IEC 61834-11
+ * 0xA1      ISO/IEC 61834-11
+ */
+#define ST_HDV_AUX_A                    0xa0
+#define ST_HDV_AUX_V                    0xa1
+
+/* Un-official time-code stream */
+#define ST_PS_TIMECODE                  0xd2
+
+/* Internal stream types >= 0x100 */
+#define ST_GST_AUDIO_RAWA52             0x181
+  /* Used when we don't yet know which stream type it will be in a PS stream */
+#define ST_GST_VIDEO_MPEG1_OR_2         0x102
+
+#define CLOCK_BASE 9LL
+#define CLOCK_FREQ (CLOCK_BASE * 10000)
+
+#define PCRTIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \
+            GST_MSECOND/10, 300 * CLOCK_BASE))
+#define MPEGTIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \
+            GST_MSECOND/10, CLOCK_BASE))
+#define GSTTIME_TO_MPEGTIME(time) (gst_util_uint64_scale ((time), \
+            CLOCK_BASE, GST_MSECOND/10))
+
+#define MPEG_MUX_RATE_MULT      50
+
+/* sync:4 == 00xx ! pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
+#define READ_TS(data, target, lost_sync_label)          \
+    if ((*data & 0x01) != 0x01) goto lost_sync_label;   \
+    target  = ((guint64) (*data++ & 0x0E)) << 29;       \
+    target |= ((guint64) (*data++       )) << 22;       \
+    if ((*data & 0x01) != 0x01) goto lost_sync_label;   \
+    target |= ((guint64) (*data++ & 0xFE)) << 14;       \
+    target |= ((guint64) (*data++       )) << 7;        \
+    if ((*data & 0x01) != 0x01) goto lost_sync_label;   \
+    target |= ((guint64) (*data++ & 0xFE)) >> 1;
+
+/* some extra GstFlowReturn values used internally */
+#define GST_FLOW_NEED_MORE_DATA   GST_FLOW_CUSTOM_SUCCESS
+#define GST_FLOW_LOST_SYNC        GST_FLOW_CUSTOM_SUCCESS_1
+
+#endif /* __GST_MPEG_DEFS_H__ */
diff --git a/gst/mpegpes/mpegpescmn.c b/gst/mpegpes/mpegpescmn.c
new file mode 100644
index 0000000..8544e1d
--- /dev/null
+++ b/gst/mpegpes/mpegpescmn.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <gst/base/gstbytereader.h>
+
+#include "pesparse.h"
+#include "mpegpesdepay.h"
+
+static gint
+add_to_queue (MpegPes * mux, GstBuffer * buf)
+{
+  gint pos;
+  if (mux->queued) {
+    pos = GST_BUFFER_SIZE (mux->queue);
+    mux->queue = gst_buffer_join (mux->queue, buf);
+  } else {
+    pos = 0;
+    mux->queue = buf;
+  }
+  mux->queued++;
+  return pos;
+}
+
+static void
+clear_queue (MpegPes * mux)
+{
+  if (mux->queued) {
+    gst_buffer_unref (mux->queue);
+    mux->queued = 0;
+  }
+}
+
+static gint
+find_sync (GstBuffer * buf, guint offs)
+{
+  GstByteReader *reader = gst_byte_reader_new_from_buffer (buf);
+  gint len = GST_BUFFER_SIZE (buf) - offs;
+  guint pos;
+  g_assert (len > 0);
+  pos = gst_byte_reader_masked_scan_uint32 (reader,
+      0xffffff00, 0x00000100, offs, len);
+  gst_byte_reader_free (reader);
+  return pos;
+}
+
+static GstFlowReturn
+push_queue (MpegPes * mux, GstPad * pad)
+{
+  mux->queued = 0;
+  return mux->push (pad, mux->queue);
+}
+
+enum HandleDelta
+{ HD_HANDLED, HD_NEED_MORE, HD_ERROR };
+
+static enum HandleDelta
+handle_delta (MpegPes * mux, GstBuffer * buf, GstPad * pad, gint * r_sync_pos)
+{
+  gint sync_pos;
+  GstFlowReturn ret;
+  sync_pos = find_sync (buf, 0);
+  if (sync_pos == 0) {
+    if (r_sync_pos)
+      *r_sync_pos = 0;
+    return HD_HANDLED;
+  }
+  if (sync_pos > 0) {
+    GstBuffer *dbuf = gst_buffer_create_sub (buf, 0, sync_pos);
+    GST_BUFFER_FLAG_SET (dbuf, MPEGPES_FLAG_UNBOUND);
+    GST_BUFFER_FLAG_SET (dbuf, MPEGPES_FLAG_UNBOUND_NO_START);
+    GST_BUFFER_FLAG_SET (dbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+    GST_BUFFER_TIMESTAMP (dbuf) = mux->cur_pts;
+    ret = mux->push (pad, dbuf);
+    if (ret != GST_FLOW_OK)
+      return HD_ERROR;
+    if (r_sync_pos)
+      *r_sync_pos = sync_pos;
+    return HD_HANDLED;
+  }
+  /* sync not here */
+  GST_BUFFER_FLAG_SET (buf, MPEGPES_FLAG_UNBOUND);
+  GST_BUFFER_FLAG_SET (buf, MPEGPES_FLAG_UNBOUND_NO_START);
+  GST_BUFFER_FLAG_SET (buf, MPEGPES_FLAG_UNBOUND_NO_END);
+  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+  GST_BUFFER_TIMESTAMP (buf) = mux->cur_pts;
+  ret = mux->push (pad, buf);
+  if (ret != GST_FLOW_OK)
+    return HD_ERROR;
+  return HD_NEED_MORE;
+}
+
+GstFlowReturn
+mpegpes_chain (MpegPes * mux, GstBuffer * buf, GstPad * pad)
+{
+  GstFlowReturn ret;
+  GstBuffer *rem;
+  gint sync_pos, buf_offs;
+  guint8 *data;
+  guint32 length;
+  PESHeader header;
+  PESParsingResult parseres;
+
+  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+
+  if (mux->is_delta) {
+    enum HandleDelta hd_ret = handle_delta (mux, buf, pad, &sync_pos);
+    switch (hd_ret) {
+      case HD_HANDLED:
+        g_assert (!mux->queued);
+        /* position to next packet */
+        GST_BUFFER_DATA (buf) += sync_pos;
+        GST_BUFFER_SIZE (buf) -= sync_pos;
+        mux->is_delta = FALSE;
+        g_assert (GST_BUFFER_SIZE (buf) > 0);
+        break;
+      case HD_NEED_MORE:
+        return GST_FLOW_OK;
+      case HD_ERROR:
+        mux->is_delta = FALSE;
+        return GST_FLOW_ERROR;
+    }
+  }
+
+do_parse:
+  g_assert (!mux->is_delta);
+  rem = NULL;
+  buf_offs = add_to_queue (mux, buf);
+  if (buf_offs == -1) {
+    clear_queue (mux);
+    return GST_FLOW_ERROR;
+  }
+  buf = mux->queue;
+
+do_parse_buf:
+  g_assert (buf);
+  data = GST_BUFFER_DATA (buf);
+  length = GST_BUFFER_SIZE (buf);
+
+  parseres = mpegts_parse_pes_header (data, length, &header, 0);
+
+  switch (parseres) {
+    case PES_PARSING_BAD:
+      g_assert (buf_offs == 0);
+      if (mux->pedantic) {
+        clear_queue (mux);
+        return GST_FLOW_ERROR;
+      }
+      sync_pos = find_sync (buf, 0);
+      if (sync_pos == -1) {
+        clear_queue (mux);
+        return GST_FLOW_OK;
+      }
+      if (sync_pos == 0) {
+        clear_queue (mux);
+        return GST_FLOW_ERROR;
+      }
+      GST_BUFFER_DATA (buf) += sync_pos;
+      GST_BUFFER_SIZE (buf) -= sync_pos;
+      goto do_parse_buf;
+    case PES_PARSING_NEED_MORE:
+      return GST_FLOW_OK;
+    case PES_PARSING_OK:
+      if (header.packet_length > length)
+        return GST_FLOW_OK;
+      if (!header.packet_length) {
+        GST_BUFFER_FLAG_SET (buf, MPEGPES_FLAG_UNBOUND);
+        sync_pos = find_sync (buf, buf_offs + header.header_size);
+        if (sync_pos == -1) {
+          if (mux->frame_unbound)
+            return GST_FLOW_OK;
+          g_assert (buf_offs == 0);
+          GST_BUFFER_FLAG_SET (buf, MPEGPES_FLAG_UNBOUND_NO_END);
+          GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+          mux->is_delta = TRUE;
+          /* will push it anyway */
+        } else {
+          /* have both start and end, just hack the header */
+          header.packet_length = buf_offs + sync_pos;
+        }
+      }
+      break;
+  }
+
+  if (header.PTS != -1) {
+    GST_DEBUG_OBJECT (mux, "PES has pts %" G_GINT64_FORMAT, header.PTS);
+    mux->cur_pts = MPEGTIME_TO_GSTTIME (header.PTS);
+  } else {
+    mux->cur_pts = GST_CLOCK_TIME_NONE;
+  }
+  if (header.DTS != -1) {
+    GST_DEBUG_OBJECT (mux, "PES has dts %" G_GINT64_FORMAT
+        ", great, but gstreamer doesnt support those", header.DTS);
+    mux->cur_dts = MPEGTIME_TO_GSTTIME (header.DTS);
+  } else {
+    mux->cur_dts = GST_CLOCK_TIME_NONE;
+  }
+  GST_BUFFER_TIMESTAMP (buf) = mux->cur_pts;
+
+  if (header.packet_length && header.packet_length < length) {
+    guint rem_len = length - header.packet_length;
+    rem = gst_buffer_create_sub (buf, header.packet_length, rem_len);
+    GST_BUFFER_SIZE (buf) -= rem_len;
+  }
+
+  if (!mux->parse_only) {
+    /* Remove PES headers */
+    GST_BUFFER_DATA (buf) += header.header_size;
+    GST_BUFFER_SIZE (buf) -= header.header_size;
+  }
+
+  ret = push_queue (mux, pad);
+  if (ret != GST_FLOW_OK)
+    return ret;
+
+  if (rem) {
+    /* parse reminder of the data buffer */
+    buf = rem;
+    goto do_parse;
+  }
+
+  return ret;
+}
+
+void
+mpegpes_init (MpegPes * mux, PushBufFunc callb)
+{
+  mux->queued = 0;
+  mux->is_delta = FALSE;
+  mux->push = callb;
+  mux->frame_unbound = FALSE;
+}
+
+void
+mpegpes_destroy (MpegPes * mux)
+{
+  clear_queue (mux);
+}
diff --git a/gst/mpegpes/mpegpescmn.h b/gst/mpegpes/mpegpescmn.h
new file mode 100644
index 0000000..579553f
--- /dev/null
+++ b/gst/mpegpes/mpegpescmn.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __MPEGPESCMN_H__
+#define __MPEGPESCMN_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+    typedef GstFlowReturn (*PushBufFunc) (GstPad * pad, GstBuffer * buf);
+
+typedef struct MpegPes MpegPes;
+
+struct MpegPes
+{
+  GstClockTime cur_pts;
+  GstClockTime cur_dts;
+  gboolean is_delta;
+  gboolean parse_only;
+  gint queued;
+  GstBuffer *queue;
+  PushBufFunc push;
+
+  gboolean pedantic;
+  gboolean frame_unbound;
+};
+
+#define CLOCK_BASE 9LL
+#define CLOCK_FREQ (CLOCK_BASE * 10000)
+
+#define MPEGTIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \
+                        GST_MSECOND/10, CLOCK_BASE))
+#define GSTTIME_TO_MPEGTIME(time) (gst_util_uint64_scale ((time), \
+                        CLOCK_BASE, GST_MSECOND/10))
+
+#define STANDARD_TIME_CLOCK     27000000
+/*33 bits as 1 ie 0x1ffffffff*/
+#define TWO_POW_33_MINUS1     ((0xffffffff * 2) - 1)
+
+#define MPEGPES_FLAG_UNBOUND            GST_BUFFER_FLAG_MEDIA1
+#define MPEGPES_FLAG_UNBOUND_NO_START   GST_BUFFER_FLAG_MEDIA2
+#define MPEGPES_FLAG_UNBOUND_NO_END     GST_BUFFER_FLAG_MEDIA3
+
+void mpegpes_init (MpegPes * mux, PushBufFunc callb);
+void mpegpes_destroy (MpegPes * mux);
+GstFlowReturn mpegpes_chain (MpegPes * mux, GstBuffer * buf, GstPad * pad);
+
+G_END_DECLS
+#endif
diff --git a/gst/mpegpes/mpegpesdepay.c b/gst/mpegpes/mpegpesdepay.c
new file mode 100644
index 0000000..422a518
--- /dev/null
+++ b/gst/mpegpes/mpegpesdepay.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <gst/base/gstbytereader.h>
+
+#include "pesparse.h"
+#include "mpegpesdepay.h"
+
+GST_DEBUG_CATEGORY (mpegpesdepay_debug);
+#define GST_CAT_DEFAULT mpegpesdepay_debug
+
+static GstStaticPadTemplate mpegpesdepay_src_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/mpeg, "
+        "systemstream = (boolean) false, "
+        "parsed = (boolean) false, " "framed = (boolean) false"));
+
+static GstStaticPadTemplate mpegpesdepay_sink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/mpegpes")
+    );
+
+static void mpegpesdepay_dispose (GObject * object);
+
+static GstFlowReturn mpegpesdepay_chain (GstPad * pad, GstBuffer * buf);
+static void mpegpesdepay_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void mpegpesdepay_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static GstFlowReturn push_buf (GstPad * pad, GstBuffer * buf);
+
+GST_BOILERPLATE (MpegPesDepay, mpegpesdepay, GstElement, GST_TYPE_ELEMENT);
+
+enum
+{
+  PROP_0,
+  PROP_PEDANTIC,
+};
+
+static void
+mpegpesdepay_base_init (gpointer g_class)
+{
+
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mpegpesdepay_sink_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mpegpesdepay_src_factory));
+
+  gst_element_class_set_details_simple (element_class,
+      "MPEG PES Depayloader", "Codec/Depayloader",
+      "Extracts Elementary Stream from PES",
+      "Stas Sergeev <stsp@users.sourceforge.net>");
+}
+
+static void
+mpegpesdepay_class_init (MpegPesDepayClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->dispose = mpegpesdepay_dispose;
+
+  gobject_class->set_property = mpegpesdepay_set_property;
+  gobject_class->get_property = mpegpesdepay_get_property;
+  g_object_class_install_property (gobject_class, PROP_PEDANTIC,
+      g_param_spec_boolean ("pedantic", "Pedantic parsing",
+          "Pedantically treat garbage data in the input stream as an error",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+mpegpesdepay_init (MpegPesDepay * mux, MpegPesDepayClass * g_class)
+{
+  mux->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&mpegpesdepay_src_factory), "src");
+  gst_pad_use_fixed_caps (mux->srcpad);
+  gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
+
+  mux->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&mpegpesdepay_sink_factory), "sink");
+  gst_pad_use_fixed_caps (mux->sinkpad);
+  gst_pad_set_chain_function (mux->sinkpad, mpegpesdepay_chain);
+  gst_element_add_pad (GST_ELEMENT (mux), mux->sinkpad);
+
+  mpegpes_init (&mux->pes, push_buf);
+  mux->pes.parse_only = FALSE;
+}
+
+static void
+mpegpesdepay_dispose (GObject * object)
+{
+  MpegPesDepay *mux = GST_MPEG_PES_DEPAY (object);
+
+  mpegpes_destroy (&mux->pes);
+
+  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+}
+
+static void
+mpegpesdepay_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  MpegPesDepay *mux = GST_MPEG_PES_DEPAY (object);
+
+  switch (prop_id) {
+    case PROP_PEDANTIC:
+      mux->pes.pedantic = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+mpegpesdepay_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  MpegPesDepay *mux = GST_MPEG_PES_DEPAY (object);
+
+  switch (prop_id) {
+    case PROP_PEDANTIC:
+      g_value_set_boolean (value, mux->pes.pedantic);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstFlowReturn
+push_buf (GstPad * pad, GstBuffer * buf)
+{
+  MpegPesDepay *mux = GST_MPEG_PES_DEPAY (GST_OBJECT_PARENT (pad));
+  gst_buffer_set_caps (buf, gst_pad_get_caps (mux->srcpad));
+  return gst_pad_push (mux->srcpad, buf);
+}
+
+static GstFlowReturn
+mpegpesdepay_chain (GstPad * pad, GstBuffer * buf)
+{
+  MpegPesDepay *mux = GST_MPEG_PES_DEPAY (GST_OBJECT_PARENT (pad));
+  return mpegpes_chain (&mux->pes, buf, pad);
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "mpegpesdepay", GST_RANK_PRIMARY,
+          mpegpesdepay_get_type ()))
+    return FALSE;
+
+  GST_DEBUG_CATEGORY_INIT (mpegpesdepay_debug, "mpegpesdepay", 0,
+      "MPEG PES depayloader");
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
+    "mpegpesdepay", "MPEG PES depayloader",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
diff --git a/gst/mpegpes/mpegpesdepay.h b/gst/mpegpes/mpegpesdepay.h
new file mode 100644
index 0000000..248a71b
--- /dev/null
+++ b/gst/mpegpes/mpegpesdepay.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __MPEGPESDEPAY_H__
+#define __MPEGPESDEPAY_H__
+
+#include <gst/gst.h>
+#include "mpegpescmn.h"
+
+G_BEGIN_DECLS
+#define GST_TYPE_MPEG_PES_DEPAY  (mpegpesdepay_get_type())
+#define GST_MPEG_PES_DEPAY(obj)  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_MPEG_PES_DEPAY, MpegPesDepay))
+typedef struct MpegPesDepay MpegPesDepay;
+typedef struct MpegPesDepayClass MpegPesDepayClass;
+
+struct MpegPesDepay
+{
+  GstElement parent;
+  GstPad *srcpad;
+  GstPad *sinkpad;
+  MpegPes pes;
+};
+
+struct MpegPesDepayClass
+{
+  GstElementClass parent_class;
+};
+
+GType mpegpesdepay_get_type (void);
+
+G_END_DECLS
+#endif
diff --git a/gst/mpegpes/mpegpesparse.c b/gst/mpegpes/mpegpesparse.c
new file mode 100644
index 0000000..8548ae5
--- /dev/null
+++ b/gst/mpegpes/mpegpesparse.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <gst/base/gstbytereader.h>
+
+#include "pesparse.h"
+#include "mpegpesparse.h"
+
+GST_DEBUG_CATEGORY (mpegpesparse_debug);
+#define GST_CAT_DEFAULT mpegpesparse_debug
+
+static GstStaticPadTemplate mpegpesparse_src_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/mpegpes, "
+        "parsed = (boolean) true, " "framed = (boolean) true"));
+
+static GstStaticPadTemplate mpegpesparse_sink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/mpegpes")
+    );
+
+static void mpegpesparse_dispose (GObject * object);
+
+static GstFlowReturn mpegpesparse_chain (GstPad * pad, GstBuffer * buf);
+static void mpegpesparse_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void mpegpesparse_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static GstFlowReturn push_buf (GstPad * pad, GstBuffer * buf);
+
+GST_BOILERPLATE (MpegPesParse, mpegpesparse, GstElement, GST_TYPE_ELEMENT);
+
+enum
+{
+  PROP_0,
+  PROP_PEDANTIC,
+  PROP_FRAME_UNBOUND
+};
+
+static void
+mpegpesparse_base_init (gpointer g_class)
+{
+
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mpegpesparse_sink_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mpegpesparse_src_factory));
+
+  gst_element_class_set_details_simple (element_class,
+      "MPEG PES Parser", "Codec/Parser",
+      "Parses packetized elementary stream",
+      "Stas Sergeev <stsp@users.sourceforge.net>");
+}
+
+static void
+mpegpesparse_class_init (MpegPesParseClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->dispose = mpegpesparse_dispose;
+
+  gobject_class->set_property = mpegpesparse_set_property;
+  gobject_class->get_property = mpegpesparse_get_property;
+  g_object_class_install_property (gobject_class, PROP_PEDANTIC,
+      g_param_spec_boolean ("pedantic", "Pedantic parsing",
+          "Pedantically treat garbage data in the input stream as an error",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_FRAME_UNBOUND,
+      g_param_spec_boolean ("frame-unbound", "Frame unbound PES packets",
+          "Try to join parts of the unbound PES packets into a single data frame",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+mpegpesparse_init (MpegPesParse * mux, MpegPesParseClass * g_class)
+{
+  mux->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&mpegpesparse_src_factory), "src");
+  gst_pad_use_fixed_caps (mux->srcpad);
+  gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
+
+  mux->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&mpegpesparse_sink_factory), "sink");
+  gst_pad_use_fixed_caps (mux->sinkpad);
+  gst_pad_set_chain_function (mux->sinkpad, mpegpesparse_chain);
+  gst_element_add_pad (GST_ELEMENT (mux), mux->sinkpad);
+
+  mpegpes_init (&mux->pes, push_buf);
+  mux->pes.parse_only = TRUE;
+}
+
+static void
+mpegpesparse_dispose (GObject * object)
+{
+  MpegPesParse *mux = GST_MPEG_PES_PARSE (object);
+
+  mpegpes_destroy (&mux->pes);
+
+  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+}
+
+static void
+mpegpesparse_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  MpegPesParse *mux = GST_MPEG_PES_PARSE (object);
+
+  switch (prop_id) {
+    case PROP_PEDANTIC:
+      mux->pes.pedantic = g_value_get_boolean (value);
+      break;
+    case PROP_FRAME_UNBOUND:
+      mux->pes.frame_unbound = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+mpegpesparse_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  MpegPesParse *mux = GST_MPEG_PES_PARSE (object);
+
+  switch (prop_id) {
+    case PROP_PEDANTIC:
+      g_value_set_boolean (value, mux->pes.pedantic);
+      break;
+    case PROP_FRAME_UNBOUND:
+      g_value_set_boolean (value, mux->pes.frame_unbound);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstFlowReturn
+push_buf (GstPad * pad, GstBuffer * buf)
+{
+  MpegPesParse *mux = GST_MPEG_PES_PARSE (GST_OBJECT_PARENT (pad));
+  gst_buffer_set_caps (buf, gst_pad_get_caps (mux->srcpad));
+  return gst_pad_push (mux->srcpad, buf);
+}
+
+static GstFlowReturn
+mpegpesparse_chain (GstPad * pad, GstBuffer * buf)
+{
+  MpegPesParse *mux = GST_MPEG_PES_PARSE (GST_OBJECT_PARENT (pad));
+  return mpegpes_chain (&mux->pes, buf, pad);
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "mpegpesparse", GST_RANK_PRIMARY,
+          mpegpesparse_get_type ()))
+    return FALSE;
+
+  GST_DEBUG_CATEGORY_INIT (mpegpesparse_debug, "mpegpesparse", 0,
+      "MPEG PES parser");
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
+    "mpegpesparse", "MPEG PES parser",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
diff --git a/gst/mpegpes/mpegpesparse.h b/gst/mpegpes/mpegpesparse.h
new file mode 100644
index 0000000..3f40855
--- /dev/null
+++ b/gst/mpegpes/mpegpesparse.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __MPEGPESPARSE_H__
+#define __MPEGPESPARSE_H__
+
+#include <gst/gst.h>
+#include "mpegpescmn.h"
+
+G_BEGIN_DECLS
+#define GST_TYPE_MPEG_PES_PARSE  (mpegpesparse_get_type())
+#define GST_MPEG_PES_PARSE(obj)  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_MPEG_PES_PARSE, MpegPesParse))
+typedef struct MpegPesParse MpegPesParse;
+typedef struct MpegPesParseClass MpegPesParseClass;
+
+struct MpegPesParse
+{
+  GstElement parent;
+  GstPad *srcpad;
+  GstPad *sinkpad;
+  MpegPes pes;
+};
+
+struct MpegPesParseClass
+{
+  GstElementClass parent_class;
+};
+
+GType mpegpesparse_get_type (void);
+
+G_END_DECLS
+#endif
diff --git a/gst/mpegpes/mpegpespay.c b/gst/mpegpes/mpegpespay.c
new file mode 100644
index 0000000..fa26789
--- /dev/null
+++ b/gst/mpegpes/mpegpespay.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * Based on the work of the following authors:
+ *  Authors: Jan Schmidt <jan@fluendo.com>
+ *           Kapil Agrawal <kapil@fluendo.com>
+ *           Julien Moutte <julien@fluendo.com>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include "mpegpespay.h"
+
+#include "mpegtsmux_h264.h"
+#include "mpegtsmux_aac.h"
+
+GST_DEBUG_CATEGORY (mpegpespay_debug);
+#define GST_CAT_DEFAULT mpegpespay_debug
+
+static GstStaticPadTemplate mpegpespay_sink_factory =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_REQUEST,
+    GST_STATIC_CAPS ("video/mpeg, "
+        "mpegversion = (int) { 1, 2, 4 }, "
+        "systemstream = (boolean) false, "
+        "framed = (boolean) true; "
+        "video/x-dirac, "
+        "framed = (boolean) true; "
+        "video/x-h264, "
+        "framed = (boolean) true; "
+        "audio/mpeg, "
+        "mpegversion = (int) { 1, 2, 4 }, "
+        "framed = (boolean) true; "
+        "audio/x-lpcm, "
+        "width = (int) { 16, 20, 24 }, "
+        "rate = (int) { 48000, 96000 }, "
+        "channels = (int) [ 1, 8 ], "
+        "dynamic_range = (int) [ 0, 255 ], "
+        "emphasis = (boolean) { FALSE, TRUE }, "
+        "mute = (boolean) { FALSE, TRUE }; "
+        "audio/x-ac3, "
+        "framed = (boolean) true; " "audio/x-dts, " "framed = (boolean) true"));
+
+static GstStaticPadTemplate mpegpespay_src_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/mpegpes")
+    );
+
+static void mpegpespay_dispose (GObject * object);
+static void release_buffer_cb (guint8 * data, void *user_data);
+
+static gboolean mpegpespay_setcaps (GstPad * pad, GstCaps * caps);
+static GstFlowReturn mpegpespay_chain (GstPad * pad, GstBuffer * buf);
+
+GST_BOILERPLATE (MpegPesPay, mpegpespay, GstElement, GST_TYPE_ELEMENT);
+
+static void
+mpegpespay_base_init (gpointer g_class)
+{
+
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mpegpespay_sink_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&mpegpespay_src_factory));
+
+  gst_element_class_set_details_simple (element_class,
+      "MPEG PES Payloader", "Codec/Payloader",
+      "Payload-encodes Elementary Stream into PES",
+      "Stas Sergeev <stsp@users.sourceforge.net>");
+}
+
+static void
+mpegpespay_class_init (MpegPesPayClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->dispose = mpegpespay_dispose;
+}
+
+static void
+mpegpespay_init (MpegPesPay * mux, MpegPesPayClass * g_class)
+{
+  mux->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&mpegpespay_src_factory), "src");
+  gst_pad_use_fixed_caps (mux->srcpad);
+  gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
+
+  mux->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&mpegpespay_sink_factory), "sink");
+  gst_pad_set_setcaps_function (mux->sinkpad, mpegpespay_setcaps);
+  gst_pad_set_chain_function (mux->sinkpad, mpegpespay_chain);
+  gst_element_add_pad (GST_ELEMENT (mux), mux->sinkpad);
+}
+
+static void
+mpegpespay_dispose (GObject * object)
+{
+  MpegPesPay *mux = GST_MPEG_PES_PAY (object);
+
+  tsmux_stream_free (mux->stream);
+
+  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+}
+
+static void
+release_buffer_cb (guint8 * data, void *user_data)
+{
+  GstBuffer *buf = (GstBuffer *) user_data;
+  gst_buffer_unref (buf);
+}
+
+static gboolean
+mpegpespay_setcaps (GstPad * pad, GstCaps * caps)
+{
+  MpegPesPay *mux = GST_MPEG_PES_PAY (GST_OBJECT_PARENT (pad));
+  gboolean ret = FALSE;
+  GstStructure *s;
+
+  s = gst_caps_get_structure (caps, 0);
+  g_return_val_if_fail (s != NULL, FALSE);
+
+  if (gst_structure_has_name (s, "video/x-dirac")) {
+    GST_DEBUG_OBJECT (pad, "Creating Dirac stream");
+    mux->stream = tsmux_stream_new (0, TSMUX_ST_VIDEO_DIRAC);
+  } else if (gst_structure_has_name (s, "audio/x-ac3")) {
+    GST_DEBUG_OBJECT (pad, "Creating AC3 stream");
+    mux->stream = tsmux_stream_new (0, TSMUX_ST_PS_AUDIO_AC3);
+  } else if (gst_structure_has_name (s, "audio/x-dts")) {
+    GST_DEBUG_OBJECT (pad, "Creating DTS stream");
+    mux->stream = tsmux_stream_new (0, TSMUX_ST_PS_AUDIO_DTS);
+  } else if (gst_structure_has_name (s, "audio/x-lpcm")) {
+    GST_DEBUG_OBJECT (pad, "Creating LPCM stream");
+    mux->stream = tsmux_stream_new (0, TSMUX_ST_PS_AUDIO_LPCM);
+  } else if (gst_structure_has_name (s, "video/x-h264")) {
+    const GValue *value;
+    GST_DEBUG_OBJECT (pad, "Creating H264 stream");
+    /* Codec data contains SPS/PPS which need to go in stream for valid ES */
+    value = gst_structure_get_value (s, "codec_data");
+    if (value) {
+      mux->codec_data = gst_buffer_ref (gst_value_get_buffer (value));
+      GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
+          GST_BUFFER_SIZE (mux->codec_data));
+      mux->prepare_func = mpegtsmux_prepare_h264;
+      mux->free_func = mpegtsmux_free_h264;
+    } else {
+      mux->codec_data = NULL;
+    }
+    mux->stream = tsmux_stream_new (0, TSMUX_ST_VIDEO_H264);
+  } else if (gst_structure_has_name (s, "audio/mpeg")) {
+    gint mpegversion;
+    if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
+      GST_ELEMENT_ERROR (pad, STREAM, FORMAT,
+          ("Invalid data format presented"),
+          ("Caps with type audio/mpeg did not have mpegversion"));
+      goto beach;
+    }
+
+    switch (mpegversion) {
+      case 1:
+        GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 1 stream");
+        mux->stream = tsmux_stream_new (0, TSMUX_ST_AUDIO_MPEG1);
+        break;
+      case 2:
+        GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 2 stream");
+        mux->stream = tsmux_stream_new (0, TSMUX_ST_AUDIO_MPEG2);
+        break;
+      case 4:
+      {
+        const GValue *value;
+        /* Codec data contains SPS/PPS which need to go in stream for valid ES */
+        value = gst_structure_get_value (s, "codec_data");
+        if (value) {
+          mux->codec_data = gst_buffer_ref (gst_value_get_buffer (value));
+          GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
+              GST_BUFFER_SIZE (mux->codec_data));
+          mux->prepare_func = mpegtsmux_prepare_aac;
+        } else {
+          mux->codec_data = NULL;
+        }
+        GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 4 stream");
+        mux->stream = tsmux_stream_new (0, TSMUX_ST_AUDIO_AAC);
+        break;
+      }
+      default:
+        GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
+        goto beach;
+    }
+  } else if (gst_structure_has_name (s, "video/mpeg")) {
+    gint mpegversion;
+    if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
+      GST_ELEMENT_ERROR (mux, STREAM, FORMAT,
+          ("Invalid data format presented"),
+          ("Caps with type video/mpeg did not have mpegversion"));
+      goto beach;
+    }
+
+    if (mpegversion == 1) {
+      GST_DEBUG_OBJECT (pad, "Creating MPEG Video, version 1 stream");
+      mux->stream = tsmux_stream_new (0, TSMUX_ST_VIDEO_MPEG1);
+    } else if (mpegversion == 2) {
+      GST_DEBUG_OBJECT (pad, "Creating MPEG Video, version 2 stream");
+      mux->stream = tsmux_stream_new (0, TSMUX_ST_VIDEO_MPEG2);
+    } else {
+      GST_DEBUG_OBJECT (pad, "Creating MPEG Video, version 4 stream");
+      mux->stream = tsmux_stream_new (0, TSMUX_ST_VIDEO_MPEG4);
+    }
+  }
+
+  if (mux->stream != NULL) {
+    gst_structure_get_int (s, "rate", &mux->stream->audio_sampling);
+    gst_structure_get_int (s, "channels", &mux->stream->audio_channels);
+    gst_structure_get_int (s, "bitrate", &mux->stream->audio_bitrate);
+
+    tsmux_stream_set_buffer_release_func (mux->stream, release_buffer_cb);
+
+    ret = TRUE;
+  }
+
+beach:
+  return ret;
+}
+
+static gboolean
+write_pes_packet (MpegPesPay * mux, GstBuffer * buf)
+{
+  GstFlowReturn ret;
+
+  GST_LOG_OBJECT (mux, "Outputting a packet of length %d",
+      GST_BUFFER_SIZE (buf));
+  gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));
+
+  GST_BUFFER_TIMESTAMP (buf) = mux->last_ts;
+
+  if (mux->is_delta) {
+    GST_LOG_OBJECT (mux, "marking as delta unit");
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+  } else {
+    GST_DEBUG_OBJECT (mux, "marking as non-delta unit");
+    mux->is_delta = TRUE;
+  }
+
+  ret = gst_pad_push (mux->srcpad, buf);
+  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+    mux->last_flow_ret = ret;
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+GstFlowReturn
+mpegpespay_chain (GstPad * pad, GstBuffer * buf)
+{
+  MpegPesPay *mux = GST_MPEG_PES_PAY (GST_OBJECT_PARENT (pad));
+  GstFlowReturn ret = GST_FLOW_OK;
+  gint64 pts = -1;
+  gboolean delta = TRUE;
+
+  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+  if (mux->stream->is_video_stream)
+    delta = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+  GST_DEBUG_OBJECT (mux, "delta: %d", delta);
+
+  if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
+    /* Ignore timestamps that go backward for now. FIXME: Handle all
+     * incoming PTS */
+    if (mux->last_ts == GST_CLOCK_TIME_NONE ||
+        mux->last_ts < GST_BUFFER_TIMESTAMP (buf)) {
+      mux->cur_ts = mux->last_ts = GST_BUFFER_TIMESTAMP (buf);
+    } else {
+      GST_DEBUG_OBJECT (mux, "Ignoring PTS that has gone backward");
+    }
+  } else
+    mux->cur_ts = GST_CLOCK_TIME_NONE;
+  /* FIXME: for video streams we may need DTS! */
+
+//  g_warning("ts=%li\n", mux->cur_ts);
+  if (GST_CLOCK_TIME_IS_VALID (mux->cur_ts)) {
+    pts = GSTTIME_TO_MPEGTIME (mux->cur_ts);
+    GST_DEBUG_OBJECT (mux, "Buffer has TS %" GST_TIME_FORMAT " pts %"
+        G_GINT64_FORMAT, GST_TIME_ARGS (mux->cur_ts), pts);
+  }
+
+  tsmux_stream_add_data (mux->stream, GST_BUFFER_DATA (buf),
+      GST_BUFFER_SIZE (buf), buf, pts, -1, !delta);
+
+  mux->is_delta = delta;
+  while (tsmux_stream_bytes_in_buffer (mux->stream) > 0) {
+    gboolean written = FALSE, got_data;
+    guint len;
+    GstBuffer *out_buf;
+    tsmux_stream_initialize_pes_packet (mux->stream);
+    len = MIN (tsmux_stream_bytes_avail (mux->stream), TSMUX_MAX_PES_LENGTH);
+    out_buf = gst_buffer_new_and_alloc (len);
+    got_data = tsmux_stream_get_data (mux->stream,
+        GST_BUFFER_DATA (out_buf), len);
+    if (got_data)
+      written = write_pes_packet (mux, out_buf);
+    if (!written) {
+      GST_DEBUG_OBJECT (mux, "Failed to write data packet");
+      goto write_fail;
+    }
+  }
+  mux->last_ts = mux->last_ts;
+
+  return ret;
+write_fail:
+  /* FIXME: Failed writing data for some reason. Should set appropriate error */
+  return mux->last_flow_ret;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "mpegpespay", GST_RANK_PRIMARY,
+          mpegpespay_get_type ()))
+    return FALSE;
+
+  GST_DEBUG_CATEGORY_INIT (mpegpespay_debug, "mpegpespay", 0,
+      "MPEG PES payloader");
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
+    "mpegpespay", "MPEG PES payloader",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
diff --git a/gst/mpegpes/mpegpespay.h b/gst/mpegpes/mpegpespay.h
new file mode 100644
index 0000000..36696c4
--- /dev/null
+++ b/gst/mpegpes/mpegpespay.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2011 Rikor IMT, Inc
+ *  Author: Stas Sergeev <stsp@users.sourceforge.net>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __MPEGPESPAY_H__
+#define __MPEGPESPAY_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+#include <tsmuxstream.h>
+#define GST_TYPE_MPEG_PES_PAY  (mpegpespay_get_type())
+#define GST_MPEG_PES_PAY(obj)  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_MPEG_PES_PAY, MpegPesPay))
+typedef struct MpegPesPay MpegPesPay;
+typedef struct MpegPesPayClass MpegPesPayClass;
+
+typedef GstBuffer *(*MpegTsPadDataPrepareFunction) (GstBuffer * buf,
+    MpegPesPay * mux);
+
+typedef void (*MpegTsPadDataFreePrepareDataFunction) (gpointer prepare_data);
+
+struct MpegPesPay
+{
+  GstElement parent;
+  GstFlowReturn last_flow_ret;
+  GstClockTime cur_ts;          /* Adjusted TS for the pulled buffer */
+  GstClockTime last_ts;
+  gboolean is_delta;
+
+  GstPad *srcpad;
+  GstPad *sinkpad;
+
+  TsMuxStream *stream;
+  GstBuffer *codec_data;        /* Optional codec data available in the caps */
+  gpointer prepare_data;        /* Opaque data pointer to a structure used by the
+                                   prepare function */
+  MpegTsPadDataPrepareFunction prepare_func;    /* Handler to prepare input data */
+  MpegTsPadDataFreePrepareDataFunction free_func;       /* Handler to free the private data */
+};
+
+struct MpegPesPayClass
+{
+  GstElementClass parent_class;
+};
+
+GType mpegpespay_get_type (void);
+
+#define CLOCK_BASE 9LL
+#define CLOCK_FREQ (CLOCK_BASE * 10000)
+
+#define MPEGTIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \
+                        GST_MSECOND/10, CLOCK_BASE))
+#define GSTTIME_TO_MPEGTIME(time) (gst_util_uint64_scale ((time), \
+                        CLOCK_BASE, GST_MSECOND/10))
+
+#define STANDARD_TIME_CLOCK     27000000
+/*33 bits as 1 ie 0x1ffffffff*/
+#define TWO_POW_33_MINUS1     ((0xffffffff * 2) - 1)
+
+G_END_DECLS
+#endif
diff --git a/gst/mpegpes/mpegtsmux_aac.c b/gst/mpegpes/mpegtsmux_aac.c
new file mode 100644
index 0000000..3e90f73
--- /dev/null
+++ b/gst/mpegpes/mpegtsmux_aac.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2006, 2007, 2008 Fluendo S.A. 
+ *  Authors: Jan Schmidt <jan@fluendo.com>
+ *           Kapil Agrawal <kapil@fluendo.com>
+ *           Julien Moutte <julien@fluendo.com>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mpegtsmux_aac.h"
+#include <string.h>
+
+GST_DEBUG_CATEGORY_EXTERN (mpegpespay_debug);
+#define GST_CAT_DEFAULT mpegpespay_debug
+
+GstBuffer *
+mpegtsmux_prepare_aac (GstBuffer * buf, MpegPesPay * mux)
+{
+  guint8 adts_header[7] = { 0, };
+  GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 7);
+  gsize out_offset = 0;
+  guint8 rate_idx = 0, channels = 0, obj_type = 0;
+
+  GST_DEBUG_OBJECT (mux, "Preparing AAC buffer for output");
+
+  /* We want the same metadata */
+  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);
+
+  /* Generate ADTS header */
+  obj_type = (GST_READ_UINT8 (GST_BUFFER_DATA (mux->codec_data)) & 0xC) >> 2;
+  obj_type++;
+  rate_idx = (GST_READ_UINT8 (GST_BUFFER_DATA (mux->codec_data)) & 0x3) << 1;
+  rate_idx |=
+      (GST_READ_UINT8 (GST_BUFFER_DATA (mux->codec_data) + 1) & 0x80) >> 7;
+  channels =
+      (GST_READ_UINT8 (GST_BUFFER_DATA (mux->codec_data) + 1) & 0x78) >> 3;
+  GST_DEBUG_OBJECT (mux, "Rate index %u, channels %u, object type %u", rate_idx,
+      channels, obj_type);
+  /* Sync point over a full byte */
+  adts_header[0] = 0xFF;
+  /* Sync point continued over first 4 bits + static 4 bits
+   * (ID, layer, protection)*/
+  adts_header[1] = 0xF1;
+  /* Object type over first 2 bits */
+  adts_header[2] = obj_type << 6;
+  /* rate index over next 4 bits */
+  adts_header[2] |= (rate_idx << 2);
+  /* channels over last 2 bits */
+  adts_header[2] |= (channels & 0x4) >> 2;
+  /* channels continued over next 2 bits + 4 bits at zero */
+  adts_header[3] = (channels & 0x3) << 6;
+  /* frame size over last 2 bits */
+  adts_header[3] |= (GST_BUFFER_SIZE (out_buf) & 0x1800) >> 11;
+  /* frame size continued over full byte */
+  adts_header[4] = (GST_BUFFER_SIZE (out_buf) & 0x1FF8) >> 3;
+  /* frame size continued first 3 bits */
+  adts_header[5] = (GST_BUFFER_SIZE (out_buf) & 0x7) << 5;
+  /* buffer fullness (0x7FF for VBR) over 5 last bits */
+  adts_header[5] |= 0x1F;
+  /* buffer fullness (0x7FF for VBR) continued over 6 first bits + 2 zeros for
+   * number of raw data blocks */
+  adts_header[6] = 0xFC;
+
+  /* Insert ADTS header */
+  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, adts_header, 7);
+  out_offset += 7;
+
+  /* Now copy complete frame */
+  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, GST_BUFFER_DATA (buf),
+      GST_BUFFER_SIZE (buf));
+
+  return out_buf;
+}
diff --git a/gst/mpegpes/mpegtsmux_aac.h b/gst/mpegpes/mpegtsmux_aac.h
new file mode 100644
index 0000000..5990275
--- /dev/null
+++ b/gst/mpegpes/mpegtsmux_aac.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2006, 2007, 2008 Fluendo S.A. 
+ *  Authors: Jan Schmidt <jan@fluendo.com>
+ *           Kapil Agrawal <kapil@fluendo.com>
+ *           Julien Moutte <julien@fluendo.com>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __MPEGTSMUX_AAC_H__
+#define __MPEGTSMUX_AAC_H__
+
+#include "mpegpespay.h"
+
+GstBuffer *mpegtsmux_prepare_aac (GstBuffer * buf, MpegPesPay * mux);
+
+#endif /* __MPEGTSMUX_AAC_H__ */
diff --git a/gst/mpegpes/mpegtsmux_h264.c b/gst/mpegpes/mpegtsmux_h264.c
new file mode 100644
index 0000000..3ec63a0
--- /dev/null
+++ b/gst/mpegpes/mpegtsmux_h264.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2006, 2007, 2008, 2009, 2010 Fluendo S.A.
+ *  Authors: Jan Schmidt <jan@fluendo.com>
+ *           Kapil Agrawal <kapil@fluendo.com>
+ *           Julien Moutte <julien@fluendo.com>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mpegtsmux_h264.h"
+#include <string.h>
+
+GST_DEBUG_CATEGORY_EXTERN (mpegpespay_debug);
+#define GST_CAT_DEFAULT mpegpespay_debug
+
+#define SPS_PPS_PERIOD GST_SECOND
+
+typedef struct PrivDataH264 PrivDataH264;
+
+struct PrivDataH264
+{
+  GstBuffer *last_codec_data;
+  GstClockTime last_resync_ts;
+  GstBuffer *cached_es;
+  guint8 nal_length_size;
+};
+
+void
+mpegtsmux_free_h264 (gpointer prepare_data)
+{
+  PrivDataH264 *h264_data = (PrivDataH264 *) prepare_data;
+  if (h264_data->cached_es) {
+    gst_buffer_unref (h264_data->cached_es);
+    h264_data->cached_es = NULL;
+  }
+  g_free (prepare_data);
+}
+
+static inline gboolean
+mpegtsmux_process_codec_data_h264 (MpegPesPay * mux)
+{
+  PrivDataH264 *h264_data;
+  gboolean ret = FALSE;
+
+  /* Initialize our private data structure for caching */
+  if (G_UNLIKELY (!mux->prepare_data)) {
+    mux->prepare_data = g_new0 (PrivDataH264, 1);
+    h264_data = (PrivDataH264 *) mux->prepare_data;
+    h264_data->last_resync_ts = GST_CLOCK_TIME_NONE;
+  }
+
+  h264_data = (PrivDataH264 *) mux->prepare_data;
+
+  /* Detect a codec data change */
+  if (h264_data->last_codec_data != mux->codec_data) {
+    if (h264_data->cached_es) {
+      gst_buffer_unref (h264_data->cached_es);
+      h264_data->cached_es = NULL;
+    }
+    ret = TRUE;
+  }
+
+  /* Generate the SPS/PPS ES header that will be prepended regularly */
+  if (G_UNLIKELY (!h264_data->cached_es)) {
+    gint offset = 4, i = 0, nb_sps = 0, nb_pps = 0;
+    gsize out_offset = 0;
+    guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
+    h264_data->last_codec_data = mux->codec_data;
+    h264_data->cached_es =
+        gst_buffer_new_and_alloc (GST_BUFFER_SIZE (mux->codec_data) * 10);
+
+    /* Get NAL length size */
+    h264_data->nal_length_size =
+        (GST_READ_UINT8 (GST_BUFFER_DATA (mux->codec_data) + offset) & 0x03) +
+        1;
+    GST_LOG_OBJECT (mux, "NAL length will be coded on %u bytes",
+        h264_data->nal_length_size);
+    offset++;
+
+    /* How many SPS */
+    nb_sps = GST_READ_UINT8 (GST_BUFFER_DATA (mux->codec_data) + offset) & 0x1f;
+    GST_DEBUG_OBJECT (mux, "we have %d Sequence Parameter Set", nb_sps);
+    offset++;
+
+    /* For each SPS */
+    for (i = 0; i < nb_sps; i++) {
+      guint16 sps_size =
+          GST_READ_UINT16_BE (GST_BUFFER_DATA (mux->codec_data) + offset);
+
+      GST_LOG_OBJECT (mux, "Sequence Parameter Set is %d bytes", sps_size);
+
+      /* Jump over SPS size */
+      offset += 2;
+
+      /* Fake a start code */
+      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
+          startcode, 4);
+      out_offset += 4;
+      /* Now push the SPS */
+      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
+          GST_BUFFER_DATA (mux->codec_data) + offset, sps_size);
+
+      out_offset += sps_size;
+      offset += sps_size;
+    }
+
+    /* How many PPS */
+    nb_pps = GST_READ_UINT8 (GST_BUFFER_DATA (mux->codec_data) + offset);
+    GST_LOG_OBJECT (mux, "we have %d Picture Parameter Set", nb_sps);
+    offset++;
+
+    /* For each PPS */
+    for (i = 0; i < nb_pps; i++) {
+      gint pps_size =
+          GST_READ_UINT16_BE (GST_BUFFER_DATA (mux->codec_data) + offset);
+
+      GST_LOG_OBJECT (mux, "Picture Parameter Set is %d bytes", pps_size);
+
+      /* Jump over PPS size */
+      offset += 2;
+
+      /* Fake a start code */
+      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
+          startcode, 4);
+      out_offset += 4;
+      /* Now push the PPS */
+      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
+          GST_BUFFER_DATA (mux->codec_data) + offset, pps_size);
+
+      out_offset += pps_size;
+      offset += pps_size;
+    }
+    GST_BUFFER_SIZE (h264_data->cached_es) = out_offset;
+    GST_DEBUG_OBJECT (mux, "generated a %" G_GSIZE_FORMAT
+        " bytes SPS/PPS header", out_offset);
+  }
+  return ret;
+}
+
+GstBuffer *
+mpegtsmux_prepare_h264 (GstBuffer * buf, MpegPesPay * mux)
+{
+  guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
+  gsize out_offset = 0, in_offset = 0;
+  GstBuffer *out_buf;
+  gboolean changed;
+  PrivDataH264 *h264_data;
+  GstClockTimeDiff diff = GST_CLOCK_TIME_NONE;
+
+  GST_DEBUG_OBJECT (mux, "Preparing H264 buffer for output");
+
+  changed = mpegtsmux_process_codec_data_h264 (mux);
+  h264_data = (PrivDataH264 *) mux->prepare_data;
+
+  if (GST_CLOCK_TIME_IS_VALID (h264_data->last_resync_ts) &&
+      GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) {
+    diff = GST_CLOCK_DIFF (h264_data->last_resync_ts,
+        GST_BUFFER_TIMESTAMP (buf));
+  }
+
+  if (changed || (GST_CLOCK_TIME_IS_VALID (diff) && diff > SPS_PPS_PERIOD)) {
+    out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2 +
+        GST_BUFFER_SIZE (h264_data->cached_es));
+    h264_data->last_resync_ts = GST_BUFFER_TIMESTAMP (buf);
+    memcpy (GST_BUFFER_DATA (out_buf), GST_BUFFER_DATA (h264_data->cached_es),
+        GST_BUFFER_SIZE (h264_data->cached_es));
+    out_offset = GST_BUFFER_SIZE (h264_data->cached_es);
+    GST_DEBUG_OBJECT (mux, "prepending SPS/PPS information to that packet");
+  } else {
+    out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2);
+  }
+
+  /* We want the same metadata */
+  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);
+
+  while (in_offset < GST_BUFFER_SIZE (buf) &&
+      out_offset < GST_BUFFER_SIZE (out_buf) - 4) {
+    guint32 nal_size = 0;
+
+    switch (h264_data->nal_length_size) {
+      case 1:
+        nal_size = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + in_offset);
+        break;
+      case 2:
+        nal_size = GST_READ_UINT16_BE (GST_BUFFER_DATA (buf) + in_offset);
+        break;
+      case 4:
+        nal_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + in_offset);
+        break;
+      default:
+        GST_WARNING_OBJECT (mux, "unsupported NAL length size %u",
+            h264_data->nal_length_size);
+    }
+    in_offset += h264_data->nal_length_size;
+
+    /* Generate an Elementary stream buffer by inserting a startcode */
+    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
+    out_offset += 4;
+    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
+        GST_BUFFER_DATA (buf) + in_offset,
+        MIN (nal_size, GST_BUFFER_SIZE (out_buf) - out_offset));
+    in_offset += nal_size;
+    out_offset += nal_size;
+  }
+
+  if (out_offset > GST_BUFFER_SIZE (out_buf)) {
+    GST_WARNING_OBJECT (mux, "Calculated buffer size %" G_GSIZE_FORMAT
+        " is greater than max expected size %u, "
+        "using max expected size (Input might not be in "
+        "avc format", out_offset, GST_BUFFER_SIZE (out_buf));
+    out_offset = GST_BUFFER_SIZE (out_buf);
+  }
+  GST_BUFFER_SIZE (out_buf) = out_offset;
+
+  return out_buf;
+}
diff --git a/gst/mpegpes/mpegtsmux_h264.h b/gst/mpegpes/mpegtsmux_h264.h
new file mode 100644
index 0000000..2dbc38f
--- /dev/null
+++ b/gst/mpegpes/mpegtsmux_h264.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2006, 2007, 2008, 2009, 2010 Fluendo S.A. 
+ *  Authors: Jan Schmidt <jan@fluendo.com>
+ *           Kapil Agrawal <kapil@fluendo.com>
+ *           Julien Moutte <julien@fluendo.com>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __MPEGTSMUX_H264_H__
+#define __MPEGTSMUX_H264_H__
+
+#include "mpegpespay.h"
+
+GstBuffer *mpegtsmux_prepare_h264 (GstBuffer * buf, MpegPesPay * mux);
+
+void mpegtsmux_free_h264 (gpointer prepare_data);
+
+#endif /* __MPEGTSMUX_H264_H__ */
diff --git a/gst/mpegpes/pesparse.c b/gst/mpegpes/pesparse.c
new file mode 100644
index 0000000..efb8ba0
--- /dev/null
+++ b/gst/mpegpes/pesparse.c
@@ -0,0 +1,426 @@
+/*
+ * pesparse.c : MPEG PES parsing utility
+ * Copyright (C) 2011 Edward Hervey <bilboed@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "pesparse.h"
+
+GST_DEBUG_CATEGORY_STATIC (pes_parser_debug);
+#define GST_CAT_DEFAULT pes_parser_debug
+
+/**
+ * mpegts_parse_pes_header:
+ * @data: data to parse (starting from, and including, the sync code)
+ * @length: size of @data in bytes
+ * @res: PESHeader to fill (only valid with #PES_PARSING_OK.
+ * @offset: Offset in @data to the data to parse. If #PES_PARSING_OK, offset to
+ *	    first byte of data after the header.
+ *
+ * Parses the mpeg-ts PES header located in @data into the @res.
+ *
+ * Returns: #PES_PARSING_OK if the header was fully parsed and valid,
+ * #PES_PARSING_BAD if the header is invalid, or #PES_PARSING_NEED_MORE if more data
+ * is needed to properly parse the header.
+ */
+PESParsingResult
+mpegts_parse_pes_header (const guint8 * data, gsize length, PESHeader * res,
+    gint offset)
+{
+  PESParsingResult ret = PES_PARSING_NEED_MORE;
+  gsize origlength = length;
+  const guint8 *origdata = data;
+  guint32 val32;
+  guint8 val8, flags;
+
+  g_return_val_if_fail (res != NULL, PES_PARSING_BAD);
+  g_return_val_if_fail (offset < length, PES_PARSING_BAD);
+
+  data += offset;
+  length -= offset;
+
+  /* The smallest valid PES header is 6 bytes (prefix + stream_id + length) */
+  if (G_UNLIKELY (length < 6))
+    goto need_more_data;
+
+  val32 = GST_READ_UINT32_BE (data);
+  data += 4;
+  length -= 4;
+  if (G_UNLIKELY ((val32 & 0xffffff00) != 0x00000100))
+    goto bad_start_code;
+
+  /* Clear the header */
+  memset (res, 0, sizeof (PESHeader));
+  res->PTS = -1;
+  res->DTS = -1;
+  res->ESCR = -1;
+
+  res->stream_id = val32 & 0x000000ff;
+
+  res->packet_length = GST_READ_UINT16_BE (data);
+  if (res->packet_length)
+    res->packet_length += 6;
+  data += 2;
+  length -= 2;
+
+  GST_LOG ("stream_id : 0x%08x , packet_length : %d", res->stream_id,
+      res->packet_length);
+
+  /* Jump if we don't need to parse anything more */
+  if (G_UNLIKELY (res->stream_id == 0xbc || res->stream_id == 0xbe
+          || res->stream_id == 0xbf || (res->stream_id >= 0xf0
+              && res->stream_id <= 0xf2) || res->stream_id == 0xff
+          || res->stream_id == 0xf8))
+    goto done_parsing;
+
+  if (G_UNLIKELY (length < 3))
+    goto need_more_data;
+
+  /* '10'                             2
+   * PES_scrambling_control           2
+   * PES_priority                     1
+   * data_alignment_indicator         1
+   * copyright                        1
+   * original_or_copy                 1 */
+  val8 = *data++;
+  if (G_UNLIKELY ((val8 & 0xc0) != 0x80))
+    goto bad_marker_1;
+  res->scrambling_control = (val8 >> 4) & 0x3;
+  res->flags = val8 & 0xf;
+
+  GST_LOG ("scrambling_control 0x%0x", res->scrambling_control);
+
+  /* PTS_DTS_flags                    2
+   * ESCR_flag                        1
+   * ES_rate_flag                     1
+   * DSM_trick_mode_flag              1
+   * additional_copy_info_flag        1
+   * PES_CRC_flag                     1
+   * PES_extension_flag               1*/
+  flags = *data++;
+  GST_DEBUG ("PES_flag 0x%02x", flags);
+
+  /* PES_header_data_length           8 */
+  res->header_size = *data++;
+  length -= 3;
+  if (G_UNLIKELY (length < res->header_size))
+    goto need_more_data;
+
+  res->header_size += 9;        /* We add 9 since that's the offset
+                                 * of the field in the header*/
+  GST_DEBUG ("header_size : %d", res->header_size);
+
+  /* PTS/DTS */
+
+  /* PTS_DTS_flags == 0x01 is invalid */
+  if (G_UNLIKELY ((flags >> 6) == 0x01))
+    goto bad_PTS_DTS_flags;
+
+  if ((flags & 0x80) == 0x80) {
+    /* PTS */
+    if (G_UNLIKELY (length < 5))
+      goto need_more_data;
+
+    READ_TS (data, res->PTS, bad_PTS_value);
+    length -= 5;
+    GST_LOG ("PTS %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
+        res->PTS, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (res->PTS)));
+
+    if ((flags & 0x40) == 0x40) {
+      /* DTS */
+      if (G_UNLIKELY (length < 5))
+        goto need_more_data;
+
+      READ_TS (data, res->DTS, bad_DTS_value);
+      length -= 5;
+
+      GST_LOG ("DTS %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
+          res->DTS, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (res->DTS)));
+    }
+  }
+
+  if (flags & 0x20) {
+    /* ESCR */
+    if (G_UNLIKELY (length < 5))
+      goto need_more_data;
+    READ_TS (data, res->ESCR, bad_ESCR_value);
+    length -= 5;
+
+    GST_LOG ("ESCR %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
+        res->ESCR, GST_TIME_ARGS (PCRTIME_TO_GSTTIME (res->ESCR)));
+  }
+
+  if (flags & 0x10) {
+    /* ES_rate */
+    if (G_UNLIKELY (length < 3))
+      goto need_more_data;
+    val32 = GST_READ_UINT32_BE (data);
+    data += 3;
+    length -= 3;
+    if (G_UNLIKELY ((val32 & 0x80000100) != 0x80000100))
+      goto bad_ES_rate;
+    res->ES_rate = ((val32 >> 9) & 0x003fffff) * 50;
+    GST_LOG ("ES_rate : %d", res->ES_rate);
+  }
+
+  if (flags & 0x08) {
+    /* DSM trick mode */
+    if (G_UNLIKELY (length < 1))
+      goto need_more_data;
+    val8 = *data++;
+    length -= 1;
+
+    res->trick_mode = val8 >> 5;
+    GST_LOG ("trick_mode 0x%x", res->trick_mode);
+
+    switch (res->trick_mode) {
+      case PES_TRICK_MODE_FAST_FORWARD:
+      case PES_TRICK_MODE_FAST_REVERSE:
+        res->intra_slice_refresh = (val8 >> 2) & 0x1;
+        res->frequency_truncation = val8 & 0x3;
+        /* passthrough */
+      case PES_TRICK_MODE_FREEZE_FRAME:
+        res->field_id = (val8 >> 3) & 0x3;
+        break;
+      case PES_TRICK_MODE_SLOW_MOTION:
+      case PES_TRICK_MODE_SLOW_REVERSE:
+        res->rep_cntrl = val8 & 0x1f;
+        break;
+      default:
+        break;
+    }
+  }
+
+  if (flags & 0x04) {
+    /* additional copy info */
+    if (G_UNLIKELY (length < 1))
+      goto need_more_data;
+    val8 = *data++;
+    length -= 1;
+
+    if (G_UNLIKELY (!(val8 & 0x80)))
+      goto bad_original_copy_info_marker;
+    res->additional_copy_info = val8 >> 1;
+    GST_LOG ("additional_copy_info : 0x%x", res->additional_copy_info);
+  }
+
+  if (flags & 0x02) {
+    /* CRC */
+    if (G_UNLIKELY (length < 2))
+      goto need_more_data;
+    res->previous_PES_packet_CRC = GST_READ_UINT16_BE (data);
+    GST_LOG ("previous_PES_packet_CRC : 0x%x", res->previous_PES_packet_CRC);
+    data += 2;
+    length -= 2;
+  }
+
+
+  /* jump if we don't have a PES extension */
+  if (!(flags & 0x01))
+    goto stuffing_byte;
+
+  if (G_UNLIKELY (length < 1))
+    goto need_more_data;
+
+  /* PES extension */
+  flags = *data++;
+  length -= 1;
+  GST_DEBUG ("PES_extension_flag 0x%02x", flags);
+
+  if (flags & 0x80) {
+    /* PES_private data */
+    if (G_UNLIKELY (length < 16))
+      goto need_more_data;
+    res->private_data = data;
+    GST_MEMDUMP ("private_data", data, 16);
+    data += 16;
+    length -= 16;
+  }
+
+  if (flags & 0x40) {
+    /* pack_header_field */
+    if (G_UNLIKELY (length < 1))
+      goto need_more_data;
+
+    val8 = *data++;
+    length -= 1;
+    if (G_UNLIKELY (length < val8))
+      goto need_more_data;
+    res->pack_header_size = val8;
+    res->pack_header = data;
+
+    GST_MEMDUMP ("Pack header data", res->pack_header, res->pack_header_size);
+
+    data += val8;
+    length -= val8;
+  }
+
+  if (flags & 0x20) {
+    /* sequence counter */
+    if (G_UNLIKELY (length < 2))
+      goto need_more_data;
+
+    val8 = *data++;
+    /* GRMBL, this is most often wrong */
+    if (G_UNLIKELY ((val8 & 0x80) != 0x80))
+      goto bad_sequence_marker1;
+    res->program_packet_sequence_counter = val8 * 0x70;
+    GST_LOG ("program_packet_sequence_counter %d",
+        res->program_packet_sequence_counter);
+
+    val8 = *data++;
+    /* GRMBL, this is most often wrong */
+    if (G_UNLIKELY ((val8 * 0x80) != 0x80))
+      goto bad_sequence_marker2;
+    res->MPEG1_MPEG2_identifier = (val8 >> 6) & 0x1;
+    res->original_stuff_length = val8 * 0x3f;
+    GST_LOG ("MPEG1_MPEG2_identifier : %d , original_stuff_length : %d",
+        res->MPEG1_MPEG2_identifier, res->original_stuff_length);
+    length -= 2;
+  }
+
+  if (flags & 0x10) {
+    /* P-STD */
+    if (G_UNLIKELY (length < 2))
+      goto need_more_data;
+    val8 = *data;
+    if (G_UNLIKELY ((val8 * 0xc0) != 0x40))
+      goto bad_P_STD_marker;
+    res->P_STD_buffer_size =
+        (GST_READ_UINT16_BE (data) & 0x1fff) << (val8 & 0x20) ? 10 : 7;
+    GST_LOG ("P_STD_buffer_size : %d", res->P_STD_buffer_size);
+    data += 2;
+    length -= 2;
+  }
+
+  if (flags & 0x01) {
+    /* Extension flag 2 */
+    if (G_UNLIKELY (length < 1))
+      goto need_more_data;
+
+    val8 = *data++;
+    length -= 1;
+
+    if (!(val8 & 0x80))
+      goto bad_extension_marker_2;
+
+    res->extension_field_length = val8 & 0x7f;
+    if (G_UNLIKELY (length < res->extension_field_length + 1))
+      goto need_more_data;
+
+    GST_LOG ("extension_field_length : %" G_GSSIZE_FORMAT,
+        res->extension_field_length);
+
+    if (res->extension_field_length) {
+      flags = *data++;
+      /* Only valid if stream_id_extension_flag == 0x0 */
+      if (!(flags & 0x80)) {
+        res->stream_id_extension = flags & 0x7f;
+        GST_LOG ("stream_id_extension : 0x%02x", res->stream_id_extension);
+        res->stream_id_extension_data = data;
+        GST_MEMDUMP ("stream_id_extension_data",
+            res->stream_id_extension_data, res->extension_field_length);
+      } else
+        GST_WARNING ("What are we meant to do ??");
+      data += res->extension_field_length;
+    }
+    length -= res->extension_field_length + 1;
+  }
+
+stuffing_byte:
+  /* Go to the expected data start position */
+  data = origdata + res->header_size;
+  length = origlength - res->header_size;
+
+done_parsing:
+  GST_DEBUG ("origlength:%" G_GSSIZE_FORMAT ", length:%" G_GSSIZE_FORMAT,
+      origlength, length);
+
+  res->header_size = origlength - length;
+  ret = PES_PARSING_OK;
+
+  return ret;
+
+  /* Errors */
+need_more_data:
+  GST_DEBUG ("Not enough data to parse PES header");
+  return ret;
+
+bad_start_code:
+  GST_WARNING ("Wrong packet start code 0x%x != 0x000001xx", val32);
+  return PES_PARSING_BAD;
+
+bad_marker_1:
+  GST_WARNING ("Wrong '0x10' marker before PES_scrambling_control (0x%02x)",
+      val8);
+  return PES_PARSING_BAD;
+
+bad_PTS_DTS_flags:
+  GST_WARNING ("Invalid '0x01' PTS_DTS_flags");
+  return PES_PARSING_BAD;
+
+bad_PTS_value:
+  GST_WARNING ("bad PTS value");
+  return PES_PARSING_BAD;
+
+bad_DTS_value:
+  GST_WARNING ("bad DTS value");
+  return PES_PARSING_BAD;
+
+bad_ESCR_value:
+  GST_WARNING ("bad ESCR value");
+  return PES_PARSING_BAD;
+
+bad_ES_rate:
+  GST_WARNING ("Invalid ES_rate markers 0x%0x", val32);
+  return PES_PARSING_BAD;
+
+bad_original_copy_info_marker:
+  GST_WARNING ("Invalid original_copy_info marker bit: 0x%0x", val8);
+  return PES_PARSING_BAD;
+
+bad_sequence_marker1:
+  GST_WARNING ("Invalid program_packet_sequence_counter marker 0x%0x", val8);
+  return PES_PARSING_BAD;
+
+bad_sequence_marker2:
+  GST_WARNING ("Invalid program_packet_sequence_counter marker 0x%0x", val8);
+  return PES_PARSING_BAD;
+
+bad_P_STD_marker:
+  GST_WARNING ("Invalid P-STD_buffer marker 0x%0x", val8);
+  return PES_PARSING_BAD;
+
+bad_extension_marker_2:
+  GST_WARNING ("Invalid extension_field_2 marker 0x%0x", val8);
+  return PES_PARSING_BAD;
+}
+
+void
+init_pes_parser (void)
+{
+  GST_DEBUG_CATEGORY_INIT (pes_parser_debug, "pesparser", 0, "MPEG PES parser");
+}
diff --git a/gst/mpegpes/pesparse.h b/gst/mpegpes/pesparse.h
new file mode 100644
index 0000000..48a937d
--- /dev/null
+++ b/gst/mpegpes/pesparse.h
@@ -0,0 +1,115 @@
+/*
+ * pesparse.h : MPEG PES parsing utility
+ * Copyright (C) 2011 Edward Hervey <bilboed@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PES_PARSE_H__
+#define __PES_PARSE_H__
+
+#include <gst/gst.h>
+#include "gstmpegdefs.h"
+
+G_BEGIN_DECLS typedef enum
+{
+  PES_FLAG_PRIORITY = 1 << 3,   /* PES_priority (present: high-priority) */
+  PES_FLAG_DATA_ALIGNMENT = 1 << 2,     /* data_alignment_indicator */
+  PES_FLAG_COPYRIGHT = 1 << 1,  /* copyright */
+  PES_FLAG_ORIGINAL_OR_COPY = 1 << 0    /* original_or_copy */
+} PESHeaderFlags;
+
+typedef enum
+{
+  PES_TRICK_MODE_FAST_FORWARD = 0x000,
+  PES_TRICK_MODE_SLOW_MOTION = 0x001,
+  PES_TRICK_MODE_FREEZE_FRAME = 0x010,
+  PES_TRICK_MODE_FAST_REVERSE = 0x011,
+  PES_TRICK_MODE_SLOW_REVERSE = 0x100,
+  /* ... */
+  PES_TRICK_MODE_INVALID = 0xfff        /* Not present or invalid */
+} PESTrickModeControl;
+
+typedef enum
+{
+  PES_FIELD_ID_TOP_ONLY = 0x00, /* Display from top field only */
+  PES_FIELD_ID_BOTTOM_ONLY = 0x01,      /* Display from bottom field only */
+  PES_FIELD_ID_COMPLETE_FRAME = 0x10,   /* Display complete frame */
+  PES_FIELD_ID_INVALID = 0x11   /* Reserved/Invalid */
+} PESFieldID;
+
+typedef enum
+{
+  PES_PARSING_OK = 0,           /* Header fully parsed and valid */
+  PES_PARSING_BAD = 1,          /* Header invalid (CRC error for ex) */
+  PES_PARSING_NEED_MORE = 2     /* Not enough data to parse header */
+} PESParsingResult;
+
+typedef struct
+{
+  guint8 stream_id;             /* See ID_* in gstmpegdefs.h */
+  guint16 packet_length;        /* The size of the remaining data
+                                 * (if 0 => unbounded packet) */
+  guint16 header_size;          /* The complete size of the PES header */
+
+  /* All remaining entries in this structure are optional */
+  guint8 scrambling_control;    /* 0x00  : Not scrambled/unspecified,
+                                 * The following are according to ETSI TS 101 154
+                                 * 0x01  : reserved for future DVB use
+                                 * 0x10  : PES packet scrambled with Even key
+                                 * 0x11  : PES packet scrambled with Odd key
+                                 */
+  PESHeaderFlags flags;
+
+  guint64 PTS;                  /* PTS (-1 if not present or invalid) */
+  guint64 DTS;                  /* DTS (-1 if not present or invalid) */
+  guint64 ESCR;                 /* ESCR (-1 if not present or invalid) */
+
+  guint32 ES_rate;              /* in bytes/seconds (0 if not present or invalid) */
+  PESTrickModeControl trick_mode;
+
+  /* Only valid for _FAST_FORWARD, _FAST_REVERSE and _FREEZE_FRAME */
+  PESFieldID field_id;
+  /* Only valid for _FAST_FORWARD and _FAST_REVERSE */
+  gboolean intra_slice_refresh;
+  guint8 frequency_truncation;
+  /* Only valid for _SLOW_FORWARD and _SLOW_REVERSE */
+  guint8 rep_cntrl;
+
+  guint8 additional_copy_info;  /* Private data */
+  guint16 previous_PES_packet_CRC;
+
+  /* Extension fields */
+  const guint8 *private_data;   /* PES_private_data, 16 bytes long */
+  guint8 pack_header_size;      /* Size of pack_header in bytes */
+  const guint8 *pack_header;
+  gint8 program_packet_sequence_counter;        /* -1 if not present or invalid */
+  gboolean MPEG1_MPEG2_identifier;
+  guint8 original_stuff_length;
+
+  guint32 P_STD_buffer_size;    /* P-STD buffer size in bytes (0 if invalid
+                                 * or not present */
+
+  gsize extension_field_length;
+  guint8 stream_id_extension;   /* Only valid if stream_id == ID_EXTENDED_STREAM_ID */
+  const guint8 *stream_id_extension_data;
+} PESHeader;
+
+PESParsingResult mpegts_parse_pes_header (const guint8 * data, gsize size,
+    PESHeader * res, gint offset);
+void init_pes_parser (void);
+G_END_DECLS
+#endif /* __PES_PARSE_H__ */
diff --git a/gst/mpegpes/tsmuxcommon.h b/gst/mpegpes/tsmuxcommon.h
new file mode 100644
index 0000000..02e3dc5
--- /dev/null
+++ b/gst/mpegpes/tsmuxcommon.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2006 BBC and Fluendo S.A.
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __TSMUX_COMMON_H__
+#define __TSMUX_COMMON_H__
+
+#include <glib.h>
+
+#undef TS_DEBUG_ON
+
+G_BEGIN_DECLS
+#define TSMUX_SYNC_BYTE 0x47
+#define TSMUX_PACKET_LENGTH 188
+#define TSMUX_HEADER_LENGTH 4
+#define TSMUX_PAYLOAD_LENGTH (TSMUX_PACKET_LENGTH - TSMUX_HEADER_LENGTH)
+#define TSMUX_MIN_ES_DESC_LEN 8
+#define TSMUX_MAX_PES_LEN_VALUE 0xffff
+#define TSMUX_MAX_PES_LENGTH (TSMUX_MAX_PES_LEN_VALUE + 6)
+#define TSMUX_MAX_PES_HEADER_LENGTH 22
+#define TSMUX_MAX_PES_PAYLOAD_LENGTH (TSMUX_MAX_PES_LENGTH - TSMUX_MAX_PES_HEADER_LENGTH)
+/* Frequency for PCR representation */
+#define TSMUX_SYS_CLOCK_FREQ (27000000L)
+/* Frequency for PTS values */
+#define TSMUX_CLOCK_FREQ (TSMUX_SYS_CLOCK_FREQ / 300)
+#define TSMUX_PACKET_FLAG_NONE            (0)
+#define TSMUX_PACKET_FLAG_ADAPTATION      (1 << 0)
+#define TSMUX_PACKET_FLAG_DISCONT         (1 << 1)
+#define TSMUX_PACKET_FLAG_RANDOM_ACCESS   (1 << 2)
+#define TSMUX_PACKET_FLAG_PRIORITY        (1 << 3)
+#define TSMUX_PACKET_FLAG_WRITE_PCR       (1 << 4)
+#define TSMUX_PACKET_FLAG_WRITE_OPCR      (1 << 5)
+#define TSMUX_PACKET_FLAG_WRITE_SPLICE    (1 << 6)
+#define TSMUX_PACKET_FLAG_WRITE_ADAPT_EXT (1 << 7)
+/* PES stream specific flags */
+#define TSMUX_PACKET_FLAG_PES_FULL_HEADER   (1 << 8)
+#define TSMUX_PACKET_FLAG_PES_WRITE_PTS     (1 << 9)
+#define TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS (1 << 10)
+#define TSMUX_PACKET_FLAG_PES_WRITE_ESCR    (1 << 11)
+#define TSMUX_PACKET_FLAG_PES_EXT_STREAMID  (1 << 12)
+/* PAT interval (1/10th sec) */
+#define TSMUX_DEFAULT_PAT_INTERVAL (TSMUX_CLOCK_FREQ / 10)
+/* PMT interval (1/10th sec) */
+#define TSMUX_DEFAULT_PMT_INTERVAL (TSMUX_CLOCK_FREQ / 10)
+typedef struct TsMuxPacketInfo TsMuxPacketInfo;
+typedef struct TsMuxProgram TsMuxProgram;
+typedef struct TsMuxStream TsMuxStream;
+
+struct TsMuxPacketInfo
+{
+  guint16 pid;
+  guint32 flags;
+
+  guint64 pcr;
+  guint64 opcr;
+
+  guint8 splice_countdown;
+
+  guint8 private_data_len;
+  guint8 private_data[256];
+
+  guint8 packet_count;          /* continuity counter */
+
+  guint stream_avail;           /* Number of payload bytes available */
+  gboolean packet_start_unit_indicator;
+};
+
+static inline void
+tsmux_put16 (guint8 ** pos, guint16 val)
+{
+  *(*pos)++ = (val >> 8) & 0xff;
+  *(*pos)++ = val & 0xff;
+}
+
+static inline void
+tsmux_put32 (guint8 ** pos, guint32 val)
+{
+  *(*pos)++ = (val >> 24) & 0xff;
+  *(*pos)++ = (val >> 16) & 0xff;
+  *(*pos)++ = (val >> 8) & 0xff;
+  *(*pos)++ = val & 0xff;
+}
+
+static inline void
+tsmux_put_ts (guint8 ** pos, guint8 id, gint64 ts)
+{
+  /* 1: 4 bit id value | TS [32..30] | marker_bit */
+  *(*pos)++ = ((id << 4) | ((ts >> 29) & 0x0E) | 0x01) & 0xff;
+  /* 2, 3: TS[29..15] | marker_bit */
+  tsmux_put16 (pos, ((ts >> 14) & 0xfffe) | 0x01);
+  /* 4, 5: TS[14..0] | marker_bit */
+  tsmux_put16 (pos, ((ts << 1) & 0xfffe) | 0x01);
+}
+
+#ifdef TS_DEBUG_ON
+#define TS_DEBUG(...) g_print(__VA_ARGS__); g_print ("\n")
+#else
+#define TS_DEBUG(...)
+#endif
+
+G_END_DECLS
+#endif
diff --git a/gst/mpegpes/tsmuxstream.c b/gst/mpegpes/tsmuxstream.c
new file mode 100644
index 0000000..98763a4
--- /dev/null
+++ b/gst/mpegpes/tsmuxstream.c
@@ -0,0 +1,900 @@
+/*
+ * Copyright 2006 BBC and Fluendo S.A. 
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "tsmuxstream.h"
+
+#define GST_CAT_DEFAULT mpegtsmux_debug
+
+static guint8 tsmux_stream_pes_header_length (TsMuxStream * stream);
+static void tsmux_stream_write_pes_header (TsMuxStream * stream, guint8 * data);
+static void tsmux_stream_find_pts_dts_within (TsMuxStream * stream, guint bound,
+    gint64 * pts, gint64 * dts);
+
+struct TsMuxStreamBuffer
+{
+  guint8 *data;
+  guint32 size;
+
+  /* PTS & DTS associated with the contents of this buffer */
+  gint64 pts;
+  gint64 dts;
+
+  gboolean random_access;
+
+  void *user_data;
+};
+
+/**
+ * tsmux_stream_new:
+ * @pid: a PID
+ * @stream_type: the stream type
+ *
+ * Create a new stream with PID of @pid and @stream_type.
+ *
+ * Returns: a new #TsMuxStream.
+ */
+TsMuxStream *
+tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type)
+{
+  TsMuxStream *stream = g_slice_new0 (TsMuxStream);
+
+  stream->state = TSMUX_STREAM_STATE_HEADER;
+  stream->pi.pid = pid;
+  stream->stream_type = stream_type;
+
+  stream->pes_payload_size = 0;
+  stream->cur_pes_payload_size = 0;
+  stream->pes_bytes_written = 0;
+
+  switch (stream_type) {
+    case TSMUX_ST_VIDEO_MPEG1:
+    case TSMUX_ST_VIDEO_MPEG2:
+    case TSMUX_ST_VIDEO_MPEG4:
+    case TSMUX_ST_VIDEO_H264:
+      /* FIXME: Assign sequential IDs? */
+      stream->id = 0xE0;
+      stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
+      stream->is_video_stream = TRUE;
+      break;
+    case TSMUX_ST_AUDIO_AAC:
+    case TSMUX_ST_AUDIO_MPEG1:
+    case TSMUX_ST_AUDIO_MPEG2:
+      /* FIXME: Assign sequential IDs? */
+      stream->id = 0xC0;
+      stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
+      break;
+    case TSMUX_ST_VIDEO_DIRAC:
+    case TSMUX_ST_PS_AUDIO_LPCM:
+    case TSMUX_ST_PS_AUDIO_AC3:
+    case TSMUX_ST_PS_AUDIO_DTS:
+      stream->id = 0xFD;
+      /* FIXME: assign sequential extended IDs? */
+      switch (stream_type) {
+        case TSMUX_ST_VIDEO_DIRAC:
+          stream->id_extended = 0x60;
+          stream->is_video_stream = TRUE;
+          break;
+        case TSMUX_ST_PS_AUDIO_LPCM:
+          stream->id_extended = 0x80;
+          break;
+        case TSMUX_ST_PS_AUDIO_AC3:
+          stream->id_extended = 0x71;
+          break;
+        case TSMUX_ST_PS_AUDIO_DTS:
+          stream->id_extended = 0x82;
+          break;
+        default:
+          break;
+      }
+      stream->pi.flags |=
+          TSMUX_PACKET_FLAG_PES_FULL_HEADER |
+          TSMUX_PACKET_FLAG_PES_EXT_STREAMID;
+      break;
+    default:
+      g_critical ("Stream type 0x%0x not yet implemented", stream_type);
+      break;
+  }
+
+  stream->last_pts = -1;
+  stream->last_dts = -1;
+
+  stream->pcr_ref = 0;
+  stream->last_pcr = -1;
+
+  return stream;
+}
+
+/**
+ * tsmux_stream_get_pid:
+ * @stream: a #TsMuxStream
+ *
+ * Get the PID of @stream.
+ *
+ * Returns: The PID of @stream. 0xffff on error.
+ */
+guint16
+tsmux_stream_get_pid (TsMuxStream * stream)
+{
+  g_return_val_if_fail (stream != NULL, G_MAXUINT16);
+
+  return stream->pi.pid;
+}
+
+/**
+ * tsmux_stream_free:
+ * @stream: a #TsMuxStream
+ *
+ * Free the resources of @stream.
+ */
+void
+tsmux_stream_free (TsMuxStream * stream)
+{
+  g_return_if_fail (stream != NULL);
+
+  g_slice_free (TsMuxStream, stream);
+}
+
+/**
+ * tsmux_stream_set_buffer_release_func:
+ * @stream: a #TsMuxStream
+ * @func: the new #TsMuxStreamBufferReleaseFunc
+ *
+ * Set the function that will be called when a a piece of data fed to @stream
+ * with tsmux_stream_add_data() can be freed. @func will be called with user
+ * data as provided with the call to tsmux_stream_add_data().
+ */
+void
+tsmux_stream_set_buffer_release_func (TsMuxStream * stream,
+    TsMuxStreamBufferReleaseFunc func)
+{
+  g_return_if_fail (stream != NULL);
+
+  stream->buffer_release = func;
+}
+
+/* Advance the current packet stream position by len bytes.
+ * Mustn't consume more than available in the current packet */
+static void
+tsmux_stream_consume (TsMuxStream * stream, guint len)
+{
+  g_assert (stream->cur_buffer != NULL);
+  g_assert (len <= stream->cur_buffer->size - stream->cur_buffer_consumed);
+
+  stream->cur_buffer_consumed += len;
+  stream->bytes_avail -= len;
+
+  if (stream->cur_buffer_consumed == 0)
+    return;
+
+  if (stream->cur_buffer->pts != -1) {
+    stream->last_pts = stream->cur_buffer->pts;
+    stream->last_dts = stream->cur_buffer->dts;
+  } else if (stream->cur_buffer->dts != -1)
+    stream->last_dts = stream->cur_buffer->dts;
+
+  if (stream->cur_buffer_consumed == stream->cur_buffer->size) {
+    /* Current packet is completed, move along */
+    stream->buffers = g_list_delete_link (stream->buffers, stream->buffers);
+
+    if (stream->buffer_release) {
+      stream->buffer_release (stream->cur_buffer->data,
+          stream->cur_buffer->user_data);
+    }
+
+    g_slice_free (TsMuxStreamBuffer, stream->cur_buffer);
+    stream->cur_buffer = NULL;
+    /* FIXME: As a hack, for unbounded streams, start a new PES packet for each
+     * incoming packet we receive. This assumes that incoming data is 
+     * packetised sensibly - ie, every video frame */
+    if (stream->cur_pes_payload_size == 0)
+      stream->state = TSMUX_STREAM_STATE_HEADER;
+  }
+}
+
+/**
+ * tsmux_stream_at_pes_start:
+ * @stream: a #TsMuxStream
+ *
+ * Check if @stream is at the start of a PES packet.
+ *
+ * Returns: TRUE if @stream is at a PES header packet.
+ */
+gboolean
+tsmux_stream_at_pes_start (TsMuxStream * stream)
+{
+  g_return_val_if_fail (stream != NULL, FALSE);
+
+  return stream->state == TSMUX_STREAM_STATE_HEADER;
+}
+
+/**
+ * tsmux_stream_bytes_avail:
+ * @stream: a #TsMuxStream
+ *
+ * Calculate how much bytes are available.
+ *
+ * Returns: The number of bytes available.
+ */
+gint
+tsmux_stream_bytes_avail (TsMuxStream * stream)
+{
+  gint bytes_avail;
+
+  g_return_val_if_fail (stream != NULL, 0);
+
+  if (stream->cur_pes_payload_size != 0)
+    bytes_avail = stream->cur_pes_payload_size - stream->pes_bytes_written;
+  else
+    bytes_avail = tsmux_stream_bytes_in_buffer (stream);
+
+  bytes_avail = MIN (bytes_avail, tsmux_stream_bytes_in_buffer (stream));
+
+  /* Calculate the number of bytes available in the current PES */
+  if (stream->state == TSMUX_STREAM_STATE_HEADER)
+    bytes_avail += tsmux_stream_pes_header_length (stream);
+
+  return bytes_avail;
+}
+
+/**
+ * tsmux_stream_bytes_in_buffer:
+ * @stream: a #TsMuxStream
+ *
+ * Calculate how much bytes are in the buffer.
+ *
+ * Returns: The number of bytes in the buffer.
+ */
+gint
+tsmux_stream_bytes_in_buffer (TsMuxStream * stream)
+{
+  g_return_val_if_fail (stream != NULL, 0);
+
+  return stream->bytes_avail;
+}
+
+/**
+ * tsmux_stream_initialize_pes_packet:
+ * @stream: a #TsMuxStream
+ *
+ * Initializes the PES packet.
+ *
+ * Returns: TRUE if we the packet was initialized.
+ */
+gboolean
+tsmux_stream_initialize_pes_packet (TsMuxStream * stream)
+{
+  if (stream->state != TSMUX_STREAM_STATE_HEADER)
+    return TRUE;
+
+  if (stream->pes_payload_size != 0) {
+    /* Use prescribed fixed PES payload size */
+    stream->cur_pes_payload_size = stream->pes_payload_size;
+    tsmux_stream_find_pts_dts_within (stream, stream->cur_pes_payload_size,
+        &stream->pts, &stream->dts);
+  } else if (stream->pi.pid && stream->is_video_stream) {
+    /* Unbounded for video streams are allowed only in TS (pid is set) */
+    stream->cur_pes_payload_size = 0;
+    tsmux_stream_find_pts_dts_within (stream,
+        tsmux_stream_bytes_in_buffer (stream), &stream->pts, &stream->dts);
+  } else {
+    /* Output a PES packet of all currently available bytes otherwise */
+    stream->cur_pes_payload_size =
+        MIN (tsmux_stream_bytes_in_buffer (stream),
+        TSMUX_MAX_PES_PAYLOAD_LENGTH);
+    tsmux_stream_find_pts_dts_within (stream, stream->cur_pes_payload_size,
+        &stream->pts, &stream->dts);
+  }
+
+  stream->pi.flags &= ~(TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS |
+      TSMUX_PACKET_FLAG_PES_WRITE_PTS);
+
+  if (stream->pts != -1 && stream->dts != -1)
+    stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS;
+  else {
+    if (stream->pts != -1)
+      stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS;
+  }
+
+  if (stream->buffers) {
+    TsMuxStreamBuffer *buf = (TsMuxStreamBuffer *) (stream->buffers->data);
+    if (buf->random_access) {
+      stream->pi.flags |= TSMUX_PACKET_FLAG_RANDOM_ACCESS;
+      stream->pi.flags |= TSMUX_PACKET_FLAG_ADAPTATION;
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+ * tsmux_stream_get_data:
+ * @stream: a #TsMuxStream
+ * @buf: a buffer to hold the result
+ * @len: the length of @buf
+ *
+ * Copy up to @len available data in @stream into the buffer @buf.
+ *
+ * Returns: TRUE if @len bytes could be retrieved.
+ */
+gboolean
+tsmux_stream_get_data (TsMuxStream * stream, guint8 * buf, guint len)
+{
+  g_return_val_if_fail (stream != NULL, FALSE);
+  g_return_val_if_fail (buf != NULL, FALSE);
+  g_return_val_if_fail (len <= TSMUX_MAX_PES_LENGTH, FALSE);
+
+  if (stream->state == TSMUX_STREAM_STATE_HEADER) {
+    guint8 pes_hdr_length;
+
+    pes_hdr_length = tsmux_stream_pes_header_length (stream);
+
+    /* Submitted buffer must be at least as large as the PES header */
+    if (len < pes_hdr_length)
+      return FALSE;
+
+    TS_DEBUG ("Writing PES header of length %u and payload %d",
+        pes_hdr_length, stream->cur_pes_payload_size);
+    tsmux_stream_write_pes_header (stream, buf);
+
+    len -= pes_hdr_length;
+    buf += pes_hdr_length;
+
+    stream->state = TSMUX_STREAM_STATE_PACKET;
+  }
+
+  if (len > (guint) tsmux_stream_bytes_avail (stream))
+    return FALSE;
+
+  stream->pes_bytes_written += len;
+
+  if (stream->cur_pes_payload_size != 0 &&
+      stream->pes_bytes_written == stream->cur_pes_payload_size) {
+    TS_DEBUG ("Finished PES packet");
+    stream->state = TSMUX_STREAM_STATE_HEADER;
+    stream->pes_bytes_written = 0;
+  }
+
+  while (len > 0) {
+    guint32 avail;
+    guint8 *cur;
+
+    if (stream->cur_buffer == NULL) {
+      /* Start next packet */
+      if (stream->buffers == NULL)
+        return FALSE;
+      stream->cur_buffer = (TsMuxStreamBuffer *) (stream->buffers->data);
+      stream->cur_buffer_consumed = 0;
+    }
+
+    /* Take as much as we can from the current buffer */
+    avail = stream->cur_buffer->size - stream->cur_buffer_consumed;
+    cur = stream->cur_buffer->data + stream->cur_buffer_consumed;
+    if (avail < len) {
+      memcpy (buf, cur, avail);
+      tsmux_stream_consume (stream, avail);
+
+      buf += avail;
+      len -= avail;
+    } else {
+      memcpy (buf, cur, len);
+      tsmux_stream_consume (stream, len);
+
+      len = 0;
+    }
+  }
+
+  return TRUE;
+}
+
+static guint8
+tsmux_stream_pes_header_length (TsMuxStream * stream)
+{
+  guint8 packet_len;
+
+  /* Calculate the length of the header for this stream */
+
+  /* start_code prefix + stream_id + pes_packet_length = 6 bytes */
+  packet_len = 6;
+
+  if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_FULL_HEADER) {
+    /* For a PES 'full header' we have at least 3 more bytes, 
+     * and then more based on flags */
+    packet_len += 3;
+    if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS) {
+      packet_len += 10;
+    } else if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_WRITE_PTS) {
+      packet_len += 5;
+    }
+    if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_EXT_STREAMID) {
+      /* Need basic extension flags (1 byte), plus 2 more bytes for the 
+       * length + extended stream id */
+      packet_len += 3;
+    }
+  }
+
+  return packet_len;
+}
+
+/* Find a PTS/DTS to write into the pes header within the next bound bytes
+ * of the data */
+static void
+tsmux_stream_find_pts_dts_within (TsMuxStream * stream, guint bound,
+    gint64 * pts, gint64 * dts)
+{
+  GList *cur;
+
+  *pts = -1;
+  *dts = -1;
+
+  for (cur = g_list_first (stream->buffers); cur != NULL;
+      cur = g_list_next (cur)) {
+    TsMuxStreamBuffer *curbuf = cur->data;
+
+    /* FIXME: This isn't quite correct - if the 'bound' is within this
+     * buffer, we don't know if the timestamp is before or after the split
+     * so we shouldn't return it */
+    if (bound <= curbuf->size) {
+      *pts = curbuf->pts;
+      *dts = curbuf->dts;
+      return;
+    }
+
+    /* Have we found a buffer with pts/dts set? */
+    if (curbuf->pts != -1 || curbuf->dts != -1) {
+      *pts = curbuf->pts;
+      *dts = curbuf->dts;
+      return;
+    }
+
+    bound -= curbuf->size;
+  }
+}
+
+static void
+tsmux_stream_write_pes_header (TsMuxStream * stream, guint8 * data)
+{
+  guint16 length_to_write;
+  guint8 hdr_len = tsmux_stream_pes_header_length (stream);
+
+  /* start_code prefix + stream_id + pes_packet_length = 6 bytes */
+  data[0] = 0x00;
+  data[1] = 0x00;
+  data[2] = 0x01;
+  data[3] = stream->id;
+  data += 4;
+
+  /* Write 2 byte PES packet length here. 0 (unbounded) is only
+   * valid for video packets */
+  if (stream->cur_pes_payload_size != 0) {
+    length_to_write = hdr_len + stream->cur_pes_payload_size - 6;
+  } else {
+    length_to_write = 0;
+  }
+
+  tsmux_put16 (&data, length_to_write);
+
+  if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_FULL_HEADER) {
+    guint8 flags = 0;
+
+    /* Not scrambled, original, not-copyrighted, data_alignment not specified */
+    *data++ = 0x81;
+
+    /* Flags */
+    if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS)
+      flags |= 0xC0;
+    else if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_WRITE_PTS)
+      flags |= 0x80;
+    if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_EXT_STREAMID)
+      flags |= 0x01;            /* Enable PES_extension_flag */
+    *data++ = flags;
+
+    /* Header length is the total pes length, 
+     * minus the 9 bytes of start codes, flags + hdr_len */
+    g_return_if_fail (hdr_len >= 9);
+    *data++ = (hdr_len - 9);
+
+    if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_WRITE_PTS_DTS) {
+      tsmux_put_ts (&data, 0x3, stream->pts);
+      tsmux_put_ts (&data, 0x1, stream->dts);
+    } else if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_WRITE_PTS) {
+      tsmux_put_ts (&data, 0x2, stream->pts);
+    }
+    if (stream->pi.flags & TSMUX_PACKET_FLAG_PES_EXT_STREAMID) {
+      guint8 ext_len;
+
+      flags = 0x0f;             /* (reserved bits) | PES_extension_flag_2 */
+      *data++ = flags;
+
+      ext_len = 1;              /* Only writing 1 byte into the extended fields */
+      *data++ = 0x80 | ext_len;
+      /* Write the extended streamID */
+      *data++ = stream->id_extended;
+    }
+  }
+}
+
+/**
+ * tsmux_stream_add_data:
+ * @stream: a #TsMuxStream
+ * @data: data to add
+ * @len: length of @data
+ * @user_data: user data to pass to release func
+ * @pts: PTS of access unit in @data
+ * @dts: DTS of access unit in @data
+ * @random_access: TRUE if random access point (keyframe)
+ *
+ * Submit @len bytes of @data into @stream. @pts and @dts can be set to the
+ * timestamp (against a 90Hz clock) of the first access unit in @data. A
+ * timestamp of -1 for @pts or @dts means unknown.
+ *
+ * @user_data will be passed to the release function as set with
+ * tsmux_stream_set_buffer_release_func() when @data can be freed.
+ */
+void
+tsmux_stream_add_data (TsMuxStream * stream, guint8 * data, guint len,
+    void *user_data, gint64 pts, gint64 dts, gboolean random_access)
+{
+  TsMuxStreamBuffer *packet;
+
+  g_return_if_fail (stream != NULL);
+
+  packet = g_slice_new (TsMuxStreamBuffer);
+  packet->data = data;
+  packet->size = len;
+  packet->user_data = user_data;
+  packet->random_access = random_access;
+
+  packet->pts = pts;
+  packet->dts = dts;
+
+  if (stream->bytes_avail == 0)
+    stream->last_pts = pts;
+
+  stream->bytes_avail += len;
+  stream->buffers = g_list_append (stream->buffers, packet);
+}
+
+/**
+ * tsmux_stream_get_es_descrs:
+ * @stream: a #TsMuxStream
+ * @buf: a buffer to hold the ES descriptor
+ * @len: the length used in @buf
+ *
+ * Write an Elementary Stream Descriptor for @stream into @buf. the number of
+ * bytes consumed in @buf will be updated in @len.
+ *
+ * @buf and @len must be at least #TSMUX_MIN_ES_DESC_LEN.
+ */
+void
+tsmux_stream_get_es_descrs (TsMuxStream * stream, guint8 * buf, guint16 * len)
+{
+  guint8 *pos;
+
+  g_return_if_fail (stream != NULL);
+
+  if (buf == NULL) {
+    if (len != NULL)
+      *len = 0;
+    return;
+  }
+
+  /* Based on the stream type, write out any descriptors to go in the 
+   * PMT ES_info field */
+  pos = buf;
+
+  /* tag (registration_descriptor), length, format_identifier */
+  switch (stream->stream_type) {
+    case TSMUX_ST_AUDIO_AAC:
+      /* FIXME */
+      break;
+    case TSMUX_ST_VIDEO_MPEG4:
+      /* FIXME */
+      break;
+    case TSMUX_ST_VIDEO_H264:
+      *pos++ = 0x05;
+      *pos++ = 8;
+      *pos++ = 0x48;            /* 'H' */
+      *pos++ = 0x44;            /* 'D' */
+      *pos++ = 0x4D;            /* 'M' */
+      *pos++ = 0x56;            /* 'V' */
+      /* FIXME : Not sure about this additional_identification_info */
+      *pos++ = 0xFF;
+      *pos++ = 0x1B;
+      *pos++ = 0x44;
+      *pos++ = 0x3F;
+      break;
+    case TSMUX_ST_VIDEO_DIRAC:
+      *pos++ = 0x05;
+      *pos++ = 4;
+      *pos++ = 0x64;            /* 'd' */
+      *pos++ = 0x72;            /* 'r' */
+      *pos++ = 0x61;            /* 'a' */
+      *pos++ = 0x63;            /* 'c' */
+      break;
+    case TSMUX_ST_PS_AUDIO_AC3:
+    {
+      *pos++ = 0x05;
+      *pos++ = 4;
+      *pos++ = 0x41;            /* 'A' */
+      *pos++ = 0x43;            /* 'C' */
+      *pos++ = 0x2D;            /* '-' */
+      *pos++ = 0x33;            /* '3' */
+
+      /* audio_stream_descriptor () | ATSC A/52-2001 Annex A
+       *
+       * descriptor_tag       8 uimsbf
+       * descriptor_length    8 uimsbf
+       * sample_rate_code     3 bslbf
+       * bsid                 5 bslbf
+       * bit_rate_code        6 bslbf
+       * surround_mode        2 bslbf
+       * bsmod                3 bslbf
+       * num_channels         4 bslbf
+       * full_svc             1 bslbf
+       * langcod              8 bslbf
+       * [...]
+       */
+      *pos++ = 0x81;
+      *pos++ = 0x04;
+
+      /* 3 bits sample_rate_code, 5 bits hardcoded bsid (default ver 8) */
+      switch (stream->audio_sampling) {
+        case 48000:
+          *pos++ = 0x08;
+          break;
+        case 44100:
+          *pos++ = 0x28;
+          break;
+        case 32000:
+          *pos++ = 0x48;
+          break;
+        default:
+          *pos++ = 0xE8;
+          break;                /* 48, 44.1 or 32 Khz */
+      }
+
+      /* 1 bit bit_rate_limit, 5 bits bit_rate_code, 2 bits suround_mode */
+      switch (stream->audio_bitrate) {
+        case 32:
+          *pos++ = 0x00 << 2;
+          break;
+        case 40:
+          *pos++ = 0x01 << 2;
+          break;
+        case 48:
+          *pos++ = 0x02 << 2;
+          break;
+        case 56:
+          *pos++ = 0x03 << 2;
+          break;
+        case 64:
+          *pos++ = 0x04 << 2;
+          break;
+        case 80:
+          *pos++ = 0x05 << 2;
+          break;
+        case 96:
+          *pos++ = 0x06 << 2;
+          break;
+        case 112:
+          *pos++ = 0x07 << 2;
+          break;
+        case 128:
+          *pos++ = 0x08 << 2;
+          break;
+        case 160:
+          *pos++ = 0x09 << 2;
+          break;
+        case 192:
+          *pos++ = 0x0A << 2;
+          break;
+        case 224:
+          *pos++ = 0x0B << 2;
+          break;
+        case 256:
+          *pos++ = 0x0C << 2;
+          break;
+        case 320:
+          *pos++ = 0x0D << 2;
+          break;
+        case 384:
+          *pos++ = 0x0E << 2;
+          break;
+        case 448:
+          *pos++ = 0x0F << 2;
+          break;
+        case 512:
+          *pos++ = 0x10 << 2;
+          break;
+        case 576:
+          *pos++ = 0x11 << 2;
+          break;
+        case 640:
+          *pos++ = 0x12 << 2;
+          break;
+        default:
+          *pos++ = 0x32 << 2;
+          break;                /* 640 Kb/s upper limit */
+      }
+
+      /* 3 bits bsmod, 4 bits num_channels, 1 bit full_svc */
+      switch (stream->audio_channels) {
+        case 1:
+          *pos++ = 0x01 << 1;
+          break;                /* 1/0 */
+        case 2:
+          *pos++ = 0x02 << 1;
+          break;                /* 2/0 */
+        case 3:
+          *pos++ = 0x0A << 1;
+          break;                /* <= 3 */
+        case 4:
+          *pos++ = 0x0B << 1;
+          break;                /* <= 4 */
+        case 5:
+          *pos++ = 0x0C << 1;
+          break;                /* <= 5 */
+        case 6:
+        default:
+          *pos++ = 0x0D << 1;
+          break;                /* <= 6 */
+      }
+
+      *pos++ = 0x00;
+
+      break;
+    }
+    case TSMUX_ST_PS_AUDIO_DTS:
+      /* FIXME */
+      break;
+    case TSMUX_ST_PS_AUDIO_LPCM:
+      /* FIXME */
+      break;
+    default:
+      break;
+  }
+
+  if (len)
+    *len = (pos - buf);
+}
+
+/**
+ * tsmux_stream_pcr_ref:
+ * @stream: a #TsMuxStream
+ *
+ * Mark the stream as being used as the PCR for some program.
+ */
+void
+tsmux_stream_pcr_ref (TsMuxStream * stream)
+{
+  g_return_if_fail (stream != NULL);
+
+  stream->pcr_ref++;
+}
+
+/**
+ * tsmux_stream_pcr_unref:
+ * @stream: a #TsMuxStream
+ *
+ * Mark the stream as no longer being used as the PCR for some program.
+ */
+void
+tsmux_stream_pcr_unref (TsMuxStream * stream)
+{
+  g_return_if_fail (stream != NULL);
+
+  stream->pcr_ref--;
+}
+
+/**
+ * tsmux_stream_is_pcr:
+ * @stream: a #TsMuxStream
+ *
+ * Check if @stream is used as the PCR for some program.
+ *
+ * Returns: TRUE if the stream is in use as the PCR for some program.
+ */
+gboolean
+tsmux_stream_is_pcr (TsMuxStream * stream)
+{
+  return stream->pcr_ref != 0;
+}
+
+/**
+ * tsmux_stream_get_pts:
+ * @stream: a #TsMuxStream
+ *
+ * Return the PTS of the last buffer that has had bytes written and
+ * which _had_ a PTS in @stream.
+ *
+ * Returns: the PTS of the last buffer in @stream.
+ */
+guint64
+tsmux_stream_get_pts (TsMuxStream * stream)
+{
+  g_return_val_if_fail (stream != NULL, -1);
+
+  return stream->last_pts;
+}
diff --git a/gst/mpegpes/tsmuxstream.h b/gst/mpegpes/tsmuxstream.h
new file mode 100644
index 0000000..eda415c
--- /dev/null
+++ b/gst/mpegpes/tsmuxstream.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2006 BBC and Fluendo S.A. 
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __TSMUXSTREAM_H__
+#define __TSMUXSTREAM_H__
+
+#include <glib.h>
+
+#include "tsmuxcommon.h"
+
+G_BEGIN_DECLS typedef enum TsMuxStreamType TsMuxStreamType;
+typedef enum TsMuxStreamState TsMuxStreamState;
+typedef struct TsMuxStreamBuffer TsMuxStreamBuffer;
+
+typedef void (*TsMuxStreamBufferReleaseFunc) (guint8 * data, void *user_data);
+
+/* Stream type assignments
+ *
+ *   0x00    ITU-T | ISO/IEC Reserved
+ *   0x01    ISO/IEC 11172 Video
+ *   0x02    ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or
+ *           ISO/IEC 11172-2 constrained parameter video
+ *           stream
+ *   0x03    ISO/IEC 11172 Audio
+ *   0x04    ISO/IEC 13818-3 Audio
+ *   0x05    ITU-T Rec. H.222.0 | ISO/IEC 13818-1
+ *           private_sections
+ *   0x06    ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES
+ *           packets containing private data
+ *   0x07    ISO/IEC 13522 MHEG
+ *   0x08    ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A
+ *           DSM CC
+ *   0x09    ITU-T Rec. H.222.1
+ *   0x0A    ISO/IEC 13818-6 type A
+ *   0x0B    ISO/IEC 13818-6 type B
+ *   0x0C    ISO/IEC 13818-6 type C
+ *   0x0D    ISO/IEC 13818-6 type D
+ *   0x0E    ISO/IEC 13818-1 auxiliary
+ * 0x0F-0x7F ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved
+ * 0x80-0xFF User Private
+ */
+enum TsMuxStreamType
+{
+  TSMUX_ST_RESERVED = 0x00,
+  TSMUX_ST_VIDEO_MPEG1 = 0x01,
+  TSMUX_ST_VIDEO_MPEG2 = 0x02,
+  TSMUX_ST_AUDIO_MPEG1 = 0x03,
+  TSMUX_ST_AUDIO_MPEG2 = 0x04,
+  TSMUX_ST_PRIVATE_SECTIONS = 0x05,
+  TSMUX_ST_PRIVATE_DATA = 0x06,
+  TSMUX_ST_MHEG = 0x07,
+  TSMUX_ST_DSMCC = 0x08,
+  TSMUX_ST_H222_1 = 0x09,
+
+  /* later extensions */
+  TSMUX_ST_AUDIO_AAC = 0x0f,
+  TSMUX_ST_VIDEO_MPEG4 = 0x10,
+  TSMUX_ST_VIDEO_H264 = 0x1b,
+
+  /* private stream types */
+  TSMUX_ST_PS_AUDIO_AC3 = 0x81,
+  TSMUX_ST_PS_AUDIO_DTS = 0x8a,
+  TSMUX_ST_PS_AUDIO_LPCM = 0x8b,
+  TSMUX_ST_PS_DVD_SUBPICTURE = 0xff,
+
+  /* Non-standard definitions */
+  TSMUX_ST_VIDEO_DIRAC = 0xD1
+};
+
+enum TsMuxStreamState
+{
+  TSMUX_STREAM_STATE_HEADER,
+  TSMUX_STREAM_STATE_PACKET
+};
+
+/* TsMuxStream receives elementary streams for parsing.
+ * Via the write_bytes() method, it can output a PES stream piecemeal */
+struct TsMuxStream
+{
+  TsMuxStreamState state;
+  TsMuxPacketInfo pi;
+  TsMuxStreamType stream_type;
+  guint8 id;                    /* stream id */
+  guint8 id_extended;           /* extended stream id (13818-1 Amdt 2) */
+
+  gboolean is_video_stream;
+
+  /* List of data buffers available for writing out */
+  GList *buffers;
+  guint32 bytes_avail;
+
+  /* Current data buffer being consumed */
+  TsMuxStreamBuffer *cur_buffer;
+  guint32 cur_buffer_consumed;
+
+  TsMuxStreamBufferReleaseFunc buffer_release;
+
+  guint16 pes_payload_size;
+  guint16 cur_pes_payload_size;
+  guint16 pes_bytes_written;
+
+  /* PTS/DTS to write if the flags in the packet info are set */
+  gint64 pts;
+  gint64 dts;
+
+  gint64 last_pts;
+  gint64 last_dts;
+
+  gint pcr_ref;
+  gint64 last_pcr;
+
+  gint audio_sampling;
+  gint audio_channels;
+  gint audio_bitrate;
+};
+
+/* stream management */
+TsMuxStream *tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type);
+void tsmux_stream_free (TsMuxStream * stream);
+
+guint16 tsmux_stream_get_pid (TsMuxStream * stream);
+
+void tsmux_stream_set_buffer_release_func (TsMuxStream * stream,
+    TsMuxStreamBufferReleaseFunc func);
+
+/* Add a new buffer to the pool of available bytes. If pts or dts are not -1, they
+ * indicate the PTS or DTS of the first access unit within this packet */
+void tsmux_stream_add_data (TsMuxStream * stream, guint8 * data, guint len,
+    void *user_data, gint64 pts, gint64 dts, gboolean random_access);
+
+void tsmux_stream_pcr_ref (TsMuxStream * stream);
+void tsmux_stream_pcr_unref (TsMuxStream * stream);
+gboolean tsmux_stream_is_pcr (TsMuxStream * stream);
+
+gboolean tsmux_stream_at_pes_start (TsMuxStream * stream);
+void tsmux_stream_get_es_descrs (TsMuxStream * stream, guint8 * buf,
+    guint16 * len);
+
+gint tsmux_stream_bytes_in_buffer (TsMuxStream * stream);
+gint tsmux_stream_bytes_avail (TsMuxStream * stream);
+gboolean tsmux_stream_initialize_pes_packet (TsMuxStream * stream);
+gboolean tsmux_stream_get_data (TsMuxStream * stream, guint8 * buf, guint len);
+
+guint64 tsmux_stream_get_pts (TsMuxStream * stream);
+
+G_END_DECLS
+#endif
