mpegtsdemux: Switch to MPEG-TS SI library
authorEdward Hervey <edward@collabora.com>
Sun, 23 Jun 2013 06:43:23 +0000 (08:43 +0200)
committerEdward Hervey <edward@collabora.com>
Wed, 3 Jul 2013 07:17:25 +0000 (09:17 +0200)
* Only mpeg-ts section packetization remains.
* Improve code to detect duplicated sections as early as possible
* Add FIXME for various issues that need fixing (but are not regressions)

https://bugzilla.gnome.org/show_bug.cgi?id=702724

12 files changed:
gst/mpegtsdemux/Makefile.am
gst/mpegtsdemux/gstmpegdefs.h
gst/mpegtsdemux/gstmpegdesc.c [deleted file]
gst/mpegtsdemux/gstmpegdesc.h
gst/mpegtsdemux/gsttsdemux.c
gst/mpegtsdemux/mpegtsbase.c
gst/mpegtsdemux/mpegtsbase.h
gst/mpegtsdemux/mpegtspacketizer.c
gst/mpegtsdemux/mpegtspacketizer.h
gst/mpegtsdemux/mpegtsparse.c
gst/mpegtsdemux/pesparse.h
gst/mpegtsdemux/tsdemux.c

index 99a6593..9fa5d4e 100644 (file)
@@ -1,18 +1,18 @@
 plugin_LTLIBRARIES = libgstmpegtsdemux.la
 
 libgstmpegtsdemux_la_SOURCES = \
-       gsttsdemux.c \
-       gstmpegdesc.c \
-       mpegtsbase.c    \
        mpegtspacketizer.c \
+       mpegtsbase.c    \
        mpegtsparse.c \
        tsdemux.c       \
+       gsttsdemux.c \
        pesparse.c
 
 libgstmpegtsdemux_la_CFLAGS = \
        $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
        $(GST_BASE_CFLAGS) $(GST_CFLAGS)
 libgstmpegtsdemux_la_LIBADD = \
+       $(top_builddir)/gst-libs/gst/mpegts/libgstmpegts-$(GST_API_VERSION).la \
        $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_API_VERSION) \
        $(GST_BASE_LIBS) $(GST_LIBS)
 libgstmpegtsdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
index 687a016..6e8d3a7 100644 (file)
 #ifndef __GST_MPEG_DEFS_H__
 #define __GST_MPEG_DEFS_H__
 
-/*
- * PES stream_id assignments:
- *
- * 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                          0xB9
-#define ID_PS_PACK_START_CODE                   0xBA
-#define ID_PS_SYSTEM_HEADER_START_CODE          0xBB
-#define ID_PS_PROGRAM_STREAM_MAP                0xBC
-#define ID_PRIVATE_STREAM_1                     0xBD
-#define ID_PADDING_STREAM                       0xBE
-#define ID_PRIVATE_STREAM_2                     0xBF
-#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_0        0xC0
-#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_32       0xDF
-#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_0        0xE0
-#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_16       0xEF
-#define ID_ECM_STREAM                           0xF0
-#define ID_EMM_STREAM                           0xF1
-#define ID_DSMCC_STREAM                         0xF2
-#define ID_ISO_IEC_13522_STREAM                 0xF3
-#define ID_ITU_TREC_H222_TYPE_A_STREAM          0xF4
-#define ID_ITU_TREC_H222_TYPE_B_STREAM          0xF5
-#define ID_ITU_TREC_H222_TYPE_C_STREAM          0xF6
-#define ID_ITU_TREC_H222_TYPE_D_STREAM          0xF7
-#define ID_ITU_TREC_H222_TYPE_E_STREAM          0xF8
-#define ID_ANCILLARY_STREAM                     0xF9
-#define ID_14496_1_SL_PACKETIZED_STREAM         0xFA
-#define ID_14496_1_SL_FLEXMUX_STREAM            0xFB
-#define ID_METADATA_STREAM                      0xFC
-#define ID_EXTENDED_STREAM_ID                   0xFD
-#define ID_RESERVED_STREAM_3                    0xFE
-#define ID_PROGRAM_STREAM_DIRECTORY             0xFF
-
-/*
- * PES stream_id_extension assignments (if stream_id == ID_EXTENDED_STREAM_ID)
- *
- *  000 0000             IPMP Control Information stream
- *  000 0001             IPMP Stream
- *  000 0010 - 001 0001  ISO/IEC 14496-17 text Streams
- *  001 0010 - 010 0001  ISO/IEC 23002-3 auxiliary video data Streams
- *  ... .... - 011 1111  Reserved
- *
- *  PRIVATE STREAM RANGES (But known as used)
- *  101 0101 - 101 1111  VC-1
- *  110 0000 - 110 1111  Dirac (VC-1)
- *
- *  111 0001             AC3 or independent sub-stream 0 of EAC3/DD+
- *                       DTS or core sub-stream
- *  111 0010             dependent sub-stream of EAC3/DD+
- *                       DTS extension sub-stream
- *                       Secondary EAC3/DD+
- *                       Secondary DTS-HD LBR
- *  111 0110             AC3 in MLP/TrueHD
- *  1xx xxxx    private_stream
- */
-#define EXT_ID_IPMP_CONTORL_INFORMATION_STREAM  0x00
-#define EXT_ID_IPMP_STREAM                     0x01
-
-/* VC-1 */
-#define EXT_ID_VC1_FIRST                       0x55
-#define EXT_ID_VC1_LAST                        0x5F
-
-/* BDMV */
-
-
-#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
-
-/* Reserved PIDs */
-#define PID_PAT                                        0x0000
-#define PID_CAT                                        0x0001
-#define PID_TSDT                               0x0002
-#define PID_IPMP_CIT                           0x0003
-#define PID_RESERVED_FIRST                      0x0004
-#define PID_RESERVED_LAST                       0x000F
-#define PID_NULL_PACKET                         0x1FFF
-
 /* Stream type assignments
  * 
  *   0x00    ITU-T | ISO/IEC Reserved
  *   0x7F    IPMP stream
  * 0x80-0xFF User Private
  */
+
+/* FIXME : Move well-defined Stream type to an enum in the mpegts library */
+
 #define ST_RESERVED                     0x00
 #define ST_VIDEO_MPEG1                  0x01
 #define ST_VIDEO_MPEG2                  0x02
 #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
-
-/* Table IDs */
-/* ITU H.222.0 / IEC 13818-1 */
-#define TABLE_ID_PROGRAM_ASSOCIATION           0x00
-#define TABLE_ID_CONDITIONAL_ACCESS            0x01
-#define TABLE_ID_TS_PROGRAM_MAP                        0x02
-#define TABLE_ID_TS_DESCRIPTION                        0x03
-#define TABLE_ID_14496_SCENE_DESCRIPTION       0x04
-#define TABLE_ID_14496_OBJET_DESCRIPTOR                0x05
-#define TABLE_ID_METADATA                      0x06
-#define TABLE_ID_IPMP_CONTROL_INFORMATION      0x07
-/* IEC 13818-6 (DSM-CC) */
-#define TABLE_ID_DSM_CC_MULTIPROTO_ENCAPSULATED_DATA   0x3A
-#define TABLE_ID_DSM_CC_U_N_MESSAGES                   0x3B
-#define TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGES         0x3C
-#define TABLE_ID_DSM_CC_STREAM_DESCRIPTORS             0x3D
-#define TABLE_ID_DSM_CC_PRIVATE_DATA                   0x3E
-#define TABLE_ID_DSM_CC_ADDRESSABLE_SECTIONS           0x3F
-/* EN 300 468 (DVB) v 1.12.1 */
-#define TABLE_ID_NETWORK_INFORMATION_ACTUAL_NETWORK    0x40
-#define TABLE_ID_NETWORK_INFORMATION_OTHER_NETWORK     0x41
-#define TABLE_ID_SERVICE_DESCRIPTION_ACTUAL_TS         0x42
-#define TABLE_ID_SERVICE_DESCRIPTION_OTHER_TS          0x46
-#define TABLE_ID_BOUQUET_ASSOCIATION                   0x4A
-#define TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_PRESENT   0x4E
-#define TABLE_ID_EVENT_INFORMATION_OTHER_TS_PRESENT    0x4F
-#define TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_SCHEDULE_1        0x50 /* First */
-#define TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_SCHEDULE_N        0x5F /* Last */
-#define TABLE_ID_EVENT_INFORMATION_OTHER_TS_SCHEDULE_1 0x60 /* First */
-#define TABLE_ID_EVENT_INFORMATION_OTHER_TS_SCHEDULE_N 0x6F /* Last */
-#define TABLE_ID_TIME_DATE                             0x70
-#define TABLE_ID_RUNNING_STATUS                                0x71
-#define TABLE_ID_STUFFING                              0x72
-#define TABLE_ID_TIME_OFFSET                           0x73
-/* TS 102 812 (MHP v1.1.3) */
-#define TABLE_ID_APPLICATION_INFORMATION_TABLE         0x74
-/* TS 102 323 (DVB TV Anytime v1.5.1) */
-#define TABLE_ID_CONTAINER                             0x75
-#define TABLE_ID_RELATED_CONTENT                       0x76
-#define TABLE_ID_CONTENT_IDENTIFIER                    0x77
-/* EN 301 192 (DVB specification for data broadcasting) */
-#define TABLE_ID_MPE_FEC                               0x78
-/* TS 102 323 (DVB TV Anytime v1.5.1) */
-#define TABLE_ID_RESOLUTION_NOTIFICATION               0x79
-/* TS 102 772 (DVB-SH Multi-Protocol Encapsulation) */
-#define TABLE_ID_MPE_IFEC                              0x7A
-/* EN 300 468 (DVB) v 1.12.1 */
-#define TABLE_ID_DISCONTINUITY_INFORMATION             0x7E
-#define TABLE_ID_SELECTION_INFORMATION                 0x7F
-/* ETR 289 (DVB Support for use of scrambling and CA) */
-#define TABLE_ID_CA_MESSAGE_ECM_0                      0x80
-#define TABLE_ID_CA_MESSAGE_ECM_1                      0x81
-#define TABLE_ID_CA_MESSAGE_SYSTEM_PRIVATE_1           0x82 /* First */
-#define TABLE_ID_CA_MESSAGE_SYSTEM_PRIVATE_N           0x8F /* Last */
-/* ... */
-/* EN 301 790 (DVB interaction channel for satellite distribution channels) */
-#define TABLE_ID_SCT                                   0xA0
-#define TABLE_ID_FCT                                   0xA1
-#define TABLE_ID_TCT                                   0xA2
-#define TABLE_ID_SPT                                   0xA3
-#define TABLE_ID_CMT                                   0xA4
-#define TABLE_ID_TBTP                                  0xA5
-#define TABLE_ID_PCR_PACKET_PAYLOAD                    0xA6
-#define TABLE_ID_TRANSMISSION_MODE_SUPPORT_PAYLOAD     0xAA
-#define TABLE_ID_TIM                                   0xB0
-#define TABLE_ID_LL_FEC_PARITY_DATA_TABLE              0xB1
-/* ATSC (FILLME) */
-/* ISDB (FILLME) */
-/* Unset */
-#define TABLE_ID_UNSET 0xFF
-
-
 #define CLOCK_BASE 9LL
 #define CLOCK_FREQ (CLOCK_BASE * 10000)
 
     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/mpegtsdemux/gstmpegdesc.c b/gst/mpegtsdemux/gstmpegdesc.c
deleted file mode 100644 (file)
index 997e603..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/* 
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, 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>
- *
- */
-
-#include <string.h>
-
-#include <gst/gst.h>
-
-#include "gstmpegdesc.h"
-
-GST_DEBUG_CATEGORY (gstmpegtsdesc_debug);
-#define GST_CAT_DEFAULT (gstmpegtsdesc_debug)
-
-static guint
-gst_mpeg_descriptor_parse_1 (guint8 * data, guint size)
-{
-#ifndef GST_DISABLE_GST_DEBUG
-  guint8 tag;
-#endif
-  guint8 length;
-
-  /* need at least 2 bytes for tag and length */
-  if (size < 2)
-    return 0;
-
-#ifndef GST_DISABLE_GST_DEBUG
-  tag = *data++;
-#else
-  data++;
-#endif
-  length = *data++;
-  size -= 2;
-
-  GST_DEBUG ("tag: 0x%02x, length: %d", tag, length);
-
-  if (length > size)
-    return 0;
-
-  GST_MEMDUMP ("tag contents:", data, length);
-
-  return length + 2;
-}
-
-gboolean
-gst_mpeg_descriptor_parse (GstMPEGDescriptor * result, guint8 * data,
-    guint size)
-{
-  guint8 *current;
-  guint consumed, total, n_desc;
-
-  g_return_val_if_fail (data != NULL, FALSE);
-
-  current = data;
-  total = 0;
-  n_desc = 0;
-  result->n_desc = 0;
-
-  do {
-    consumed = gst_mpeg_descriptor_parse_1 (current, size);
-
-    if (consumed > 0) {
-      current += consumed;
-      total += consumed;
-      size -= consumed;
-      n_desc++;
-    }
-  }
-  while (consumed > 0);
-
-  GST_DEBUG ("parsed %d descriptors", n_desc);
-
-  if (total == 0)
-    return FALSE;
-
-  result->n_desc = n_desc;
-  result->data_length = total;
-  result->data = data;
-
-  return TRUE;
-}
-
-guint
-gst_mpeg_descriptor_n_desc (GstMPEGDescriptor * desc)
-{
-  g_return_val_if_fail (desc != NULL, 0);
-
-  return desc->n_desc;
-}
-
-guint8 *
-gst_mpeg_descriptor_find (GstMPEGDescriptor * desc, gint tag)
-{
-  guint8 length;
-  guint8 *current;
-  guint size;
-
-  g_return_val_if_fail (desc != NULL, NULL);
-
-  current = desc->data;
-  length = desc->data_length;
-
-  while (length > 0) {
-    if (DESC_TAG (current) == tag)
-      return current;
-
-    size = DESC_LENGTH (current) + 2;
-
-    current += size;
-    length -= size;
-  }
-  return NULL;
-}
-
-/* array needs freeing afterwards */
-GArray *
-gst_mpeg_descriptor_find_all (GstMPEGDescriptor * desc, gint tag)
-{
-  GArray *all;
-
-  guint8 length;
-  guint8 *current;
-  guint size;
-
-  g_return_val_if_fail (desc != NULL, NULL);
-  all = g_array_new (TRUE, TRUE, sizeof (guint8 *));
-
-  current = desc->data;
-  length = desc->data_length;
-
-  while (length > 0) {
-    if (DESC_TAG (current) == tag)
-      g_array_append_val (all, current);
-    size = DESC_LENGTH (current) + 2;
-
-    current += size;
-    length -= size;
-  }
-
-  GST_DEBUG ("found tag 0x%02x %d times", tag, all->len);
-
-  return all;
-}
-
-guint8 *
-gst_mpeg_descriptor_nth (GstMPEGDescriptor * desc, guint i)
-{
-  guint8 length;
-  guint8 *current;
-  guint size;
-
-  g_return_val_if_fail (desc != NULL, NULL);
-
-  if (i > desc->n_desc)
-    return NULL;
-
-  current = desc->data;
-  length = desc->data_length;
-
-  while (length > 0) {
-    if (i == 0)
-      return current;
-
-    size = DESC_LENGTH (current) + 2;
-
-    current += size;
-    length -= size;
-    i--;
-
-  }
-  return NULL;
-}
-
-void
-gst_mpegtsdesc_init_debug (void)
-{
-  GST_DEBUG_CATEGORY_INIT (gstmpegtsdesc_debug, "mpegtsdesc", 0,
-      "MPEG transport stream parser (descriptor)");
-}
index 1092122..22fa679 100644 (file)
 
 #include <glib.h>
 
-/*
- * descriptor_tag TS  PS                      Identification
- *        0       n/a n/a Reserved
- *        1       n/a n/a Reserved
- *        2        X   X  video_stream_descriptor
- *        3        X   X  audio_stream_descriptor
- *        4        X   X  hierarchy_descriptor
- *        5        X   X  registration_descriptor
- *        6        X   X  data_stream_alignment_descriptor
- *        7        X   X  target_background_grid_descriptor
- *        8        X   X  video_window_descriptor
- *        9        X   X  CA_descriptor
- *       10        X   X  ISO_639_language_descriptor
- *       11        X   X  system_clock_descriptor
- *       12        X   X  multiplex_buffer_utilization_descriptor
- *       13        X   X  copyright_descriptor
- *       14        X      maximum bitrate descriptor
- *       15        X   X  private data indicator descriptor
- *       16        X   X  smoothing buffer descriptor
- *       17        X      STD_descriptor
- *       18        X   X  IBP descriptor
- *      19-63     n/a n/a ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved
- *     64-255     n/a n/a User Private
- */
-#define DESC_VIDEO_STREAM                     0x02
-#define DESC_AUDIO_STREAM                     0x03
-#define DESC_HIERARCHY                        0x04
-#define DESC_REGISTRATION                     0x05
-#define DESC_DATA_STREAM_ALIGNMENT            0x06
-#define DESC_TARGET_BACKGROUND_GRID           0x07
-#define DESC_VIDEO_WINDOW                     0x08
-#define DESC_CA                               0x09
-#define DESC_ISO_639_LANGUAGE                 0x0A
-#define DESC_SYSTEM_CLOCK                     0x0B
-#define DESC_MULTIPLEX_BUFFER_UTILISATION     0x0C
-#define DESC_COPYRIGHT                        0x0D
-#define DESC_MAXIMUM_BITRATE                  0x0E
-#define DESC_PRIVATE_DATA_INDICATOR           0x0F
-#define DESC_SMOOTHING_BUFFER                 0x10
-#define DESC_STD                              0x11
-#define DESC_IBP                              0x12
-
-/* 19-26 Defined in ISO/IEC 13818-6 (Extensions for DSM-CC) */
-#define DESC_DVB_CAROUSEL_IDENTIFIER          0x13
-
-/* 27-54 Later additions to ISO/IEC 13818-1 (H222.0 06/2012) */
-#define DESC_MPEG4_VIDEO                      0x1B
-#define DESC_MPEG4_AUDIO                      0x1C
-#define DESC_IOD                              0x1D
-#define DESC_SL                               0x1E
-#define DESC_FMC                              0x1F
-#define DESC_EXTERNAL_ES_ID                   0x20
-#define DESC_MUX_CODE                         0x21
-#define DESC_FMX_BUFFER_SIZE                  0x22
-#define DESC_MULTIPLEX_BUFFER                 0x23
-#define DESC_CONTENT_LABELING                 0x24
-#define DESC_METADATA_POINTER                 0x25
-#define DESC_METADATA                         0x26
-#define DESC_METADATA_STD                     0x27
-#define DESC_AVC_VIDEO                        0x28
-/* defined in ISO/IEC 13818-11, MPEG-2 IPMP */
-#define DESC_IPMP                             0x29
-#define DESC_AVC_TIMING_AND_HRD               0x2A
-#define DESC_MPEG2_AAC_AUDIO                  0x2B
-#define DESC_FLEX_MUX_TIMING                  0x2C
-#define DESC_MPEG4_TEXT                       0x2D
-#define DESC_MPEG4_AUDIO_EXTENSION            0x2E
-#define DESC_AUXILIARY_VIDEO_STREAM           0x2F
-#define DESC_SVC_EXTENSION                    0x30
-#define DESC_MVC_EXTENSION                    0x31
-#define DESC_J2K_VIDEO                        0x32
-#define DESC_MVC_OPERATION_POINT              0x33
-#define DESC_MPEG2_STEREOSCOPIC_VIDEO_FORMAT  0x34
-#define DESC_STEREOSCOPIC_PROGRAM_INFO        0x35
-#define DESC_STEREOSCOPIC_VIDEO_INFO          0x36
-
-/* 55-63 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved */
-
-/* 64-127 DVB tags ETSI EN 300 468
- * (Specification for Service Information (SI) in DVB systems)
- */
-#define DESC_DVB_NETWORK_NAME                 0x40
-#define DESC_DVB_SERVICE_LIST                 0x41
-#define DESC_DVB_STUFFING                     0x42
-#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM    0x43
-#define DESC_DVB_CABLE_DELIVERY_SYSTEM        0x44
-#define DESC_DVB_VBI_DATA                     0x45
-#define DESC_DVB_VBI_TELETEXT                 0x46
-#define DESC_DVB_BOUQUET_NAME                 0x47
-#define DESC_DVB_SERVICE                      0x48
-#define DESC_DVB_COUNTRY_AVAILABILITY         0x49
-#define DESC_DVB_LINKAGE                      0x4A
-#define DESC_DVB_NVOD_REFERENCE               0x4B
-#define DESC_DVB_TIME_SHIFTED_SERVICE         0x4C
-#define DESC_DVB_SHORT_EVENT                  0x4D
-#define DESC_DVB_EXTENDED_EVENT               0x4E
-#define DESC_DVB_TIME_SHIFTED_EVENT           0x4F
-#define DESC_DVB_COMPONENT                    0x50
-#define DESC_DVB_MOSAIC                       0x51
-#define DESC_DVB_STREAM_IDENTIFIER            0x52
-#define DESC_DVB_CA_IDENTIFIER                0x53
-#define DESC_DVB_CONTENT                      0x54
-#define DESC_DVB_PARENTAL_RATING              0x55
-#define DESC_DVB_TELETEXT                     0x56
-#define DESC_DVB_TELEPHONE                    0x57
-#define DESC_DVB_LOCAL_TIME_OFFSET            0x58
-#define DESC_DVB_SUBTITLING                   0x59
-#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM  0x5A
-#define DESC_DVB_MULTILINGUAL_NETWORK_NAME    0x5B
-#define DESC_DVB_MULTILINGUAL_BOUQUET_NAME    0x5C
-#define DESC_DVB_MULTILINGUAL_SERVICE_NAME    0x5D
-#define DESC_DVB_MULTILINGUAL_COMPONENT       0x5E
-#define DESC_DVB_PRIVATE_DATA                 0x5F
-#define DESC_DVB_SERVICE_MOVE                 0x60
-#define DESC_DVB_SHORT_SMOOTHING_BUFFER       0x61
-#define DESC_DVB_FREQUENCY_LIST               0x62
-#define DESC_DVB_PARTIAL_TRANSPORT_STREAM     0x63
-#define DESC_DVB_DATA_BROADCAST               0x64
-#define DESC_DVB_SCRAMBLING                   0x65
-#define DESC_DVB_DATA_BROADCAST_ID            0x66
-#define DESC_DVB_TRANSPORT_STREAM             0x67
-#define DESC_DVB_DSNG                         0x68
-#define DESC_DVB_PDC                          0x69
-#define DESC_DVB_AC3                          0x6A
-#define DESC_DVB_ANCILLARY_DATA               0x6B
-#define DESC_DVB_CELL_LIST                    0x6C
-#define DESC_DVB_CELL_FREQUENCY_LINK          0x6D
-#define DESC_DVB_ANNOUNCEMENT_SUPPORT         0x6E
-#define DESC_DVB_APPLICATION_SIGNALLING       0x6F
-#define DESC_DVB_ADAPTATION_FIELD_DATA        0x70
-#define DESC_DVB_SERVICE_IDENTIFIER           0x71
-#define DESC_DVB_SERVICE_AVAILABILITY         0x72
-#define DESC_DVB_DEFAULT_AUTHORITY            0x73
-#define DESC_DVB_RELATED_CONTENT              0x74
-#define DESC_DVB_TVA_ID                       0x75
-#define DESC_DVB_CONTENT_IDENTIFIER           0x76
-#define DESC_DVB_TIMESLICE_FEC_IDENTIFIER     0x77
-#define DESC_DVB_ECM_REPETITION_RATE          0x78
-#define DESC_DVB_S2_SATELLITE_DELIVERY_SYSTEM 0x79
-#define DESC_DVB_ENHANCED_AC3                 0x7A
-#define DESC_DVB_DTS                          0x7B
-#define DESC_DVB_AAC                          0x7C
-/* 0x7D and 0x7E are reserved for future use */
-#define DESC_DVB_EXTENSION                    0x7F
-
-/* 0x80 - 0xFE are user defined */
-#define DESC_AC3_AUDIO_STREAM                 0x81
-#define DESC_DTG_LOGICAL_CHANNEL              0x83    /* from DTG D-Book */
-
-/* ATSC A/65 2009 */
-#define DESC_ATSC_STUFFING                    0x80
-#define DESC_ATSC_AC3                         0x83
-#define DESC_ATSC_CAPTION_SERVICE             0x86
-#define DESC_ATSC_CONTENT_ADVISORY            0x87
-#define DESC_ATSC_EXTENDED_CHANNEL_NAME       0xA0
-#define DESC_ATSC_SERVICE_LOCATION            0xA1
-#define DESC_ATSC_TIME_SHIFTED_SERVICE        0xA2
-#define DESC_ATSC_COMPONENT_NAME              0xA3
-#define DESC_ATSC_DCC_DEPARTING_REQUEST       0xA8
-#define DESC_ATSC_DCC_ARRIVING_REQUEST        0xA9
-#define DESC_ATSC_REDISTRIBUTION_CONTROL      0xAA
-#define DESC_ATSC_GENRE                       0xAB
-#define DESC_ATSC_PRIVATE_INFORMATION         0xAD
-
-/* ATSC A/53:3 2009 */
-#define DESC_ATSC_ENHANCED_SIGNALING          0xB2
-
-/* ATSC A/90 */
-#define DESC_ATSC_ASSOCIATION_TAG             0x14
-#define DESC_ATSC_DATA_SERVICE                0xA4
-#define DESC_ATSC_PID_COUNT                   0xA5
-#define DESC_ATSC_DOWNLOAD_DESCRIPTOR         0xA6
-#define DESC_ATSC_MULTIPROTOCOL_ENCAPSULATION 0xA7
-#define DESC_ATSC_MODULE_LINK                 0xB4
-#define DESC_ATSC_CRC32                       0xB5
-#define DESC_ATSC_GROUP_LINK                  0xB8
 
 /* Others */
-#define DESC_DIRAC_TC_PRIVATE                 0xAC
 
 
 /* 0xFF is forbidden */
 /* AC3_audio_stream_descriptor */
 #define DESC_AC_AUDIO_STREAM_bsid(desc)             ((desc)[2] & 0x1f)
 
+/* FIXME : Move list of well know registration ids to an enum
+ * in the mpegts library.
+ *
+ * See http://www.smpte-ra.org/mpegreg/mpegreg.html for a full list
+ * */
+
 /* registration_descriptor format IDs */
 #define DRF_ID_HDMV       0x48444d56
 #define DRF_ID_VC1        0x56432D31   /* defined in RP227 */
 #define DRF_ID_DTS3       0x44545333
 #define DRF_ID_S302M      0x42535344
 
-typedef struct
-{
-  guint n_desc;
-  guint8 data_length;
-  guint8 *data;
-} GstMPEGDescriptor;
-
-G_GNUC_INTERNAL void gst_mpegtsdesc_init_debug (void);
-G_GNUC_INTERNAL gboolean gst_mpeg_descriptor_parse (GstMPEGDescriptor *result, guint8 * data, guint size);
-
-G_GNUC_INTERNAL guint gst_mpeg_descriptor_n_desc             (GstMPEGDescriptor * desc);
-G_GNUC_INTERNAL guint8 *gst_mpeg_descriptor_find             (GstMPEGDescriptor * desc, gint tag);
-G_GNUC_INTERNAL GArray *gst_mpeg_descriptor_find_all         (GstMPEGDescriptor * desc, gint tag);
-
-G_GNUC_INTERNAL guint8 *gst_mpeg_descriptor_nth              (GstMPEGDescriptor * desc, guint i);
-
 #endif /* __GST_MPEG_DESC_H__ */
index 39eee56..18f67f3 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #endif
 
+#include <gst/mpegts/mpegts.h>
 #include "mpegtsbase.h"
 #include "mpegtspacketizer.h"
 #include "mpegtsparse.h"
@@ -30,6 +31,7 @@
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
+  gst_mpegts_initialize ();
   if (!gst_mpegtsbase_plugin_init (plugin))
     return FALSE;
   if (!gst_mpegtsparse_plugin_init (plugin))
index 7b76c13..bbef7ff 100644 (file)
 #include "config.h"
 #endif
 
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
-
 #include <stdlib.h>
 #include <string.h>
 
@@ -72,14 +68,9 @@ enum
   /* FILL ME */
 };
 
-static void mpegts_base_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void mpegts_base_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
 static void mpegts_base_dispose (GObject * object);
 static void mpegts_base_finalize (GObject * object);
 static void mpegts_base_free_program (MpegTSBaseProgram * program);
-static void mpegts_base_free_stream (MpegTSBaseStream * ptream);
 static gboolean mpegts_base_sink_activate (GstPad * pad, GstObject * parent);
 static gboolean mpegts_base_sink_activate_mode (GstPad * pad,
     GstObject * parent, GstPadMode mode, gboolean active);
@@ -89,12 +80,9 @@ static gboolean mpegts_base_sink_event (GstPad * pad, GstObject * parent,
     GstEvent * event);
 static GstStateChangeReturn mpegts_base_change_state (GstElement * element,
     GstStateChange transition);
-static void mpegts_base_get_tags_from_sdt (MpegTSBase * base,
-    GstStructure * sdt_info);
-static void mpegts_base_get_tags_from_eit (MpegTSBase * base,
-    GstStructure * eit_info);
-static gboolean
-remove_each_program (gpointer key, MpegTSBaseProgram * program,
+static gboolean mpegts_base_get_tags_from_eit (MpegTSBase * base,
+    GstMpegTSSection * section);
+static gboolean remove_each_program (gpointer key, MpegTSBaseProgram * program,
     MpegTSBase * base);
 
 static void
@@ -112,65 +100,6 @@ _extra_init (void)
 G_DEFINE_TYPE_WITH_CODE (MpegTSBase, mpegts_base, GST_TYPE_ELEMENT,
     _extra_init ());
 
-static const guint32 crc_tab[256] = {
-  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
-  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
-  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
-  0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
-  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
-  0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
-  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
-  0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
-  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
-  0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
-  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
-  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
-  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
-  0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
-  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
-  0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
-  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
-  0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
-  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
-  0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
-  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
-  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
-  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
-  0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
-  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
-  0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
-  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
-  0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
-  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
-  0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
-  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
-  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
-  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
-  0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
-  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
-  0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
-  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
-  0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
-  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
-  0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
-  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
-  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
-  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
-};
-
-/* relicenced to LGPL from fluendo ts demuxer */
-static guint32
-mpegts_base_calc_crc32 (guint8 * data, guint datalen)
-{
-  gint i;
-  guint32 crc = 0xffffffff;
-
-  for (i = 0; i < datalen; i++) {
-    crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *data++) & 0xff];
-  }
-  return crc;
-}
-
 static void
 mpegts_base_class_init (MpegTSBaseClass * klass)
 {
@@ -184,11 +113,8 @@ mpegts_base_class_init (MpegTSBaseClass * klass)
       gst_static_pad_template_get (&sink_template));
 
   gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->set_property = mpegts_base_set_property;
-  gobject_class->get_property = mpegts_base_get_property;
   gobject_class->dispose = mpegts_base_dispose;
   gobject_class->finalize = mpegts_base_finalize;
-
 }
 
 static void
@@ -200,6 +126,9 @@ mpegts_base_reset (MpegTSBase * base)
   memset (base->is_pes, 0, 1024);
   memset (base->known_psi, 0, 1024);
 
+  /* FIXME : Actually these are not *always* know SI streams
+   * depending on the variant of mpeg-ts being used. */
+
   /* Known PIDs : PAT, TSDT, IPMP CIT */
   MPEGTS_BIT_SET (base->known_psi, 0);
   MPEGTS_BIT_SET (base->known_psi, 2);
@@ -209,6 +138,9 @@ mpegts_base_reset (MpegTSBase * base)
   /* network synchronization */
   MPEGTS_BIT_SET (base->known_psi, 0x15);
 
+  /* ATSC */
+  MPEGTS_BIT_SET (base->known_psi, 0x1ffb);
+
   /* FIXME : Commenting the Following lines is to be in sync with the following
    * commit
    *
@@ -283,7 +215,7 @@ mpegts_base_finalize (GObject * object)
   MpegTSBase *base = GST_MPEGTS_BASE (object);
 
   if (base->pat) {
-    gst_structure_free (base->pat);
+    g_array_unref (base->pat);
     base->pat = NULL;
   }
   g_hash_table_destroy (base->programs);
@@ -292,63 +224,24 @@ mpegts_base_finalize (GObject * object)
     G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static void
-mpegts_base_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  /* MpegTSBase *base = GST_MPEGTS_BASE (object); */
-
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-  }
-}
-
-static void
-mpegts_base_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  /* MpegTSBase *base = GST_MPEGTS_BASE (object); */
-
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-  }
-}
 
 /* returns NULL if no matching descriptor found *
  * otherwise returns a descriptor that needs to *
  * be freed */
-guint8 *
+/* FIXME : Return the GstMpegTSDescriptor */
+const guint8 *
 mpegts_get_descriptor_from_stream (MpegTSBaseStream * stream, guint8 tag)
 {
-  GValueArray *descriptors = NULL;
-  GstStructure *stream_info = stream->stream_info;
-  guint8 *retval = NULL;
-  int i;
-
-  if (!gst_structure_has_field_typed (stream_info, "descriptors",
-          G_TYPE_VALUE_ARRAY))
-    goto beach;
-
-  gst_structure_get (stream_info, "descriptors", G_TYPE_VALUE_ARRAY,
-      &descriptors, NULL);
+  const GstMpegTSDescriptor *desc;
+  GstMpegTSPMTStream *pmt = stream->stream;
 
-  for (i = 0; i < descriptors->n_values; i++) {
-    GValue *value = g_value_array_get_nth (descriptors, i);
-    GString *desc = g_value_dup_boxed (value);
-    if (DESC_TAG (desc->str) == tag && !retval) {
-      retval = (guint8 *) desc->str;
-      g_string_free (desc, FALSE);
-      break;
-    } else {
-      g_string_free (desc, TRUE);
-    }
-  }
-  g_value_array_free (descriptors);
+  GST_DEBUG ("Searching for tag 0x%02x in stream 0x%04x (stream_type 0x%02x)",
+      tag, stream->pid, stream->stream_type);
 
-beach:
-  return retval;
+  desc = gst_mpegts_find_descriptor (pmt->descriptors, tag);
+  if (desc)
+    return desc->descriptor_data;
+  return NULL;
 }
 
 typedef struct
@@ -383,39 +276,18 @@ mpegts_pid_in_active_programs (MpegTSBase * base, guint16 pid)
 /* returns NULL if no matching descriptor found *
  * otherwise returns a descriptor that needs to *
  * be freed */
-guint8 *
+/* FIXME : Return the GstMpegTSDescriptor */
+const guint8 *
 mpegts_get_descriptor_from_program (MpegTSBaseProgram * program, guint8 tag)
 {
-  GValueArray *descriptors = NULL;
-  GstStructure *program_info;
-  guint8 *retval = NULL;
-  int i;
-
-  if (G_UNLIKELY (program == NULL))
-    goto beach;
-
-  program_info = program->pmt_info;
-  if (!gst_structure_has_field_typed (program_info, "descriptors",
-          G_TYPE_VALUE_ARRAY))
-    goto beach;
-
-  gst_structure_get (program_info, "descriptors", G_TYPE_VALUE_ARRAY,
-      &descriptors, NULL);
+  const GstMpegTSDescriptor *descriptor;
+  const GstMpegTSPMT *pmt = program->pmt;
 
-  for (i = 0; i < descriptors->n_values; i++) {
-    GValue *value = g_value_array_get_nth (descriptors, i);
-    GString *desc = g_value_dup_boxed (value);
-    if (DESC_TAG (desc->str) == tag && !retval) {
-      retval = (guint8 *) desc->str;
-      g_string_free (desc, FALSE);
-      break;
-    } else
-      g_string_free (desc, TRUE);
-  }
-  g_value_array_free (descriptors);
+  descriptor = gst_mpegts_find_descriptor (pmt->descriptors, tag);
+  if (descriptor)
+    return descriptor->descriptor_data;
 
-beach:
-  return retval;
+  return NULL;
 }
 
 static MpegTSBaseProgram *
@@ -449,6 +321,10 @@ mpegts_base_add_program (MpegTSBase * base,
   program = mpegts_base_new_program (base, program_number, pmt_pid);
 
   /* Mark the PMT PID as being a known PSI PID */
+  if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, pmt_pid))) {
+    GST_FIXME ("Refcounting. Setting twice a PID (0x%04x) as known PSI",
+        pmt_pid);
+  }
   MPEGTS_BIT_SET (base->known_psi, pmt_pid);
 
   g_hash_table_insert (base->programs,
@@ -488,11 +364,13 @@ mpegts_base_free_program (MpegTSBaseProgram * program)
 {
   GList *tmp;
 
-  if (program->pmt_info)
-    gst_structure_free (program->pmt_info);
+  if (program->pmt) {
+    gst_mpegts_section_unref (program->section);
+    program->pmt = NULL;
+  }
 
   for (tmp = program->stream_list; tmp; tmp = tmp->next)
-    mpegts_base_free_stream ((MpegTSBaseStream *) tmp->data);
+    g_free (tmp->data);
   if (program->stream_list)
     g_list_free (program->stream_list);
 
@@ -515,13 +393,12 @@ mpegts_base_remove_program (MpegTSBase * base, gint program_number)
 static MpegTSBaseStream *
 mpegts_base_program_add_stream (MpegTSBase * base,
     MpegTSBaseProgram * program, guint16 pid, guint8 stream_type,
-    GstStructure * stream_info)
+    GstMpegTSPMTStream * stream)
 {
   MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base);
-  MpegTSBaseStream *stream;
+  MpegTSBaseStream *bstream;
 
-  GST_DEBUG ("pid:0x%04x, stream_type:0x%03x, stream_info:%" GST_PTR_FORMAT,
-      pid, stream_type, stream_info);
+  GST_DEBUG ("pid:0x%04x, stream_type:0x%03x", pid, stream_type);
 
   if (G_UNLIKELY (program->streams[pid])) {
     if (stream_type != 0xff)
@@ -529,24 +406,18 @@ mpegts_base_program_add_stream (MpegTSBase * base,
     return NULL;
   }
 
-  stream = g_malloc0 (base->stream_size);
-  stream->pid = pid;
-  stream->stream_type = stream_type;
-  stream->stream_info = stream_info;
+  bstream = g_malloc0 (base->stream_size);
+  bstream->pid = pid;
+  bstream->stream_type = stream_type;
+  bstream->stream = stream;
 
-  program->streams[pid] = stream;
-  program->stream_list = g_list_append (program->stream_list, stream);
+  program->streams[pid] = bstream;
+  program->stream_list = g_list_append (program->stream_list, bstream);
 
   if (klass->stream_added)
-    klass->stream_added (base, stream, program);
+    klass->stream_added (base, bstream, program);
 
-  return stream;
-}
-
-static void
-mpegts_base_free_stream (MpegTSBaseStream * stream)
-{
-  g_free (stream);
+  return bstream;
 }
 
 void
@@ -571,24 +442,18 @@ mpegts_base_program_remove_stream (MpegTSBase * base,
     klass->stream_removed (base, stream);
 
   program->stream_list = g_list_remove_all (program->stream_list, stream);
-  mpegts_base_free_stream (stream);
+  g_free (stream);
   program->streams[pid] = NULL;
 }
 
 /* Return TRUE if programs are equal */
 static gboolean
 mpegts_base_is_same_program (MpegTSBase * base, MpegTSBaseProgram * oldprogram,
-    guint16 new_pmt_pid, GstStructure * new_pmt_info)
+    guint16 new_pmt_pid, const GstMpegTSPMT * new_pmt)
 {
   guint i, nbstreams;
-  guint pcr_pid;
-  guint pid;
-  guint stream_type;
-  GstStructure *stream;
   MpegTSBaseStream *oldstream;
   gboolean sawpcrpid = FALSE;
-  const GValue *new_streams;
-  const GValue *value;
 
   if (oldprogram->pmt_pid != new_pmt_pid) {
     GST_DEBUG ("Different pmt_pid (new:0x%04x, old:0x%04x)", new_pmt_pid,
@@ -596,36 +461,29 @@ mpegts_base_is_same_program (MpegTSBase * base, MpegTSBaseProgram * oldprogram,
     return FALSE;
   }
 
-  gst_structure_id_get (new_pmt_info, QUARK_PCR_PID, G_TYPE_UINT, &pcr_pid,
-      NULL);
-  if (oldprogram->pcr_pid != pcr_pid) {
+  if (oldprogram->pcr_pid != new_pmt->pcr_pid) {
     GST_DEBUG ("Different pcr_pid (new:0x%04x, old:0x%04x)",
-        pcr_pid, oldprogram->pcr_pid);
+        new_pmt->pcr_pid, oldprogram->pcr_pid);
     return FALSE;
   }
 
   /* Check the streams */
-  new_streams = gst_structure_id_get_value (new_pmt_info, QUARK_STREAMS);
-  nbstreams = gst_value_list_get_size (new_streams);
-
+  nbstreams = new_pmt->streams->len;
   for (i = 0; i < nbstreams; ++i) {
-    value = gst_value_list_get_value (new_streams, i);
-    stream = g_value_get_boxed (value);
+    GstMpegTSPMTStream *stream = g_ptr_array_index (new_pmt->streams, i);
 
-    gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid,
-        QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL);
-    oldstream = oldprogram->streams[pid];
+    oldstream = oldprogram->streams[stream->pid];
     if (!oldstream) {
-      GST_DEBUG ("New stream 0x%04x not present in old program", pid);
+      GST_DEBUG ("New stream 0x%04x not present in old program", stream->pid);
       return FALSE;
     }
-    if (oldstream->stream_type != stream_type) {
+    if (oldstream->stream_type != stream->stream_type) {
       GST_DEBUG
           ("New stream 0x%04x has a different stream type (new:%d, old:%d)",
-          pid, stream_type, oldstream->stream_type);
+          stream->pid, stream->stream_type, oldstream->stream_type);
       return FALSE;
     }
-    if (pid == oldprogram->pcr_pid)
+    if (stream->pid == oldprogram->pcr_pid)
       sawpcrpid = TRUE;
   }
 
@@ -646,11 +504,7 @@ mpegts_base_is_same_program (MpegTSBase * base, MpegTSBaseProgram * oldprogram,
 static void
 mpegts_base_deactivate_program (MpegTSBase * base, MpegTSBaseProgram * program)
 {
-  gint i, nbstreams;
-  guint pid;
-  GstStructure *stream;
-  const GValue *streams;
-  const GValue *value;
+  gint i;
   MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base);
 
   if (G_UNLIKELY (program->active == FALSE))
@@ -660,21 +514,16 @@ mpegts_base_deactivate_program (MpegTSBase * base, MpegTSBaseProgram * program)
 
   program->active = FALSE;
 
-  if (program->pmt_info) {
-    streams = gst_structure_id_get_value (program->pmt_info, QUARK_STREAMS);
-    nbstreams = gst_value_list_get_size (streams);
-
-    for (i = 0; i < nbstreams; ++i) {
-      value = gst_value_list_get_value (streams, i);
-      stream = g_value_get_boxed (value);
+  if (program->pmt) {
+    for (i = 0; i < program->pmt->streams->len; ++i) {
+      GstMpegTSPMTStream *stream = g_ptr_array_index (program->pmt->streams, i);
 
-      gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid, NULL);
-      mpegts_base_program_remove_stream (base, program, (guint16) pid);
+      mpegts_base_program_remove_stream (base, program, stream->pid);
 
       /* Only unset the is_pes bit if the PID isn't used in any other active
        * program */
-      if (!mpegts_pid_in_active_programs (base, pid))
-        MPEGTS_BIT_UNSET (base->is_pes, pid);
+      if (!mpegts_pid_in_active_programs (base, stream->pid))
+        MPEGTS_BIT_UNSET (base->is_pes, stream->pid);
     }
 
     /* remove pcr stream */
@@ -693,15 +542,10 @@ mpegts_base_deactivate_program (MpegTSBase * base, MpegTSBaseProgram * program)
 
 static void
 mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program,
-    guint16 pmt_pid, GstStructure * pmt_info, gboolean initial_program)
+    guint16 pmt_pid, GstMpegTSSection * section, const GstMpegTSPMT * pmt,
+    gboolean initial_program)
 {
-  guint i, nbstreams;
-  guint pcr_pid;
-  guint pid;
-  guint stream_type;
-  GstStructure *stream;
-  const GValue *new_streams;
-  const GValue *value;
+  guint i;
   MpegTSBaseClass *klass;
 
   if (G_UNLIKELY (program->active))
@@ -709,34 +553,37 @@ mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program,
 
   GST_DEBUG ("Activating program %d", program->program_number);
 
-  gst_structure_id_get (pmt_info, QUARK_PCR_PID, G_TYPE_UINT, &pcr_pid, NULL);
-
   /* activate new pmt */
-  if (program->pmt_info)
-    gst_structure_free (program->pmt_info);
+  if (program->section)
+    gst_mpegts_section_unref (program->section);
+  program->section = gst_mpegts_section_ref (section);
 
-  program->pmt_info = pmt_info;
+  program->pmt = pmt;
   program->pmt_pid = pmt_pid;
-  program->pcr_pid = pcr_pid;
-
-  new_streams = gst_structure_id_get_value (pmt_info, QUARK_STREAMS);
-  nbstreams = gst_value_list_get_size (new_streams);
-
-  for (i = 0; i < nbstreams; ++i) {
-    value = gst_value_list_get_value (new_streams, i);
-    stream = g_value_get_boxed (value);
+  program->pcr_pid = pmt->pcr_pid;
+
+  for (i = 0; i < pmt->streams->len; ++i) {
+    GstMpegTSPMTStream *stream = g_ptr_array_index (pmt->streams, i);
+
+    if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->is_pes, stream->pid)))
+      GST_FIXME ("Refcounting issue. Setting twice a PID (0x%04x) as known PES",
+          stream->pid);
+    if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, stream->pid))) {
+      GST_FIXME
+          ("Refcounting issue. Setting a known PSI PID (0x%04x) as known PES",
+          stream->pid);
+      MPEGTS_BIT_UNSET (base->known_psi, stream->pid);
+    }
 
-    gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid,
-        QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL);
-    MPEGTS_BIT_SET (base->is_pes, pid);
+    MPEGTS_BIT_SET (base->is_pes, stream->pid);
     mpegts_base_program_add_stream (base, program,
-        (guint16) pid, (guint8) stream_type, stream);
+        stream->pid, stream->stream_type, stream);
 
   }
   /* We add the PCR pid last. If that PID is already used by one of the media
    * streams above, no new stream will be created */
-  mpegts_base_program_add_stream (base, program, (guint16) pcr_pid, -1, NULL);
-  MPEGTS_BIT_SET (base->is_pes, pcr_pid);
+  mpegts_base_program_add_stream (base, program, pmt->pcr_pid, -1, NULL);
+  MPEGTS_BIT_SET (base->is_pes, pmt->pcr_pid);
 
   program->active = TRUE;
   program->initial_program = initial_program;
@@ -745,14 +592,28 @@ mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program,
   if (klass->program_started != NULL)
     klass->program_started (base, program);
 
-  GST_DEBUG_OBJECT (base, "new pmt %" GST_PTR_FORMAT, pmt_info);
+  GST_DEBUG_OBJECT (base, "new pmt activated");
 }
 
+/* FIXME : This method is fundamentally wrong (and potentially expensive)
+ * A packet is only a PSI if it's from a known PSI stream.
+ *
+ * The proper fix is to ensure the rest of mpegtsbase properly ensures
+ * that PSI streams are properly detected.
+ *
+ * This requires:
+ * * Initially setting all PSI PID which are generic accross formats
+ * * When we know the "variant" of the stream (Bluray, DVB, ATSC, ISDB,...)
+ *   we properly set the expected PSI
+ * * Properly unsetting expected know-PSI PID the moment we see a program
+ *   using that PID for PES (it's not uncommon for example for ATSC streams
+ *   to use 0x0010 as a PES PID).
+ **/
 static inline gboolean
 mpegts_base_is_psi (MpegTSBase * base, MpegTSPacketizerPacket * packet)
 {
   gboolean retval = FALSE;
-  guint8 *data, table_id = TABLE_ID_UNSET, pointer;
+  guint8 *data, table_id = GST_MTS_TABLE_ID_UNSET, pointer;
   int i;
 
   static const guint8 si_tables[] =
@@ -761,7 +622,7 @@ mpegts_base_is_psi (MpegTSBase * base, MpegTSPacketizerPacket * packet)
     0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65,
     0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
     0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7E, 0x7F,
-    TABLE_ID_UNSET
+    GST_MTS_TABLE_ID_UNSET
   };
 
   /* check if it is a pes pid */
@@ -791,13 +652,13 @@ mpegts_base_is_psi (MpegTSBase * base, MpegTSPacketizerPacket * packet)
         base->packetizer->streams[packet->pid];
 
     if (stream)
-      table_id = stream->section_table_id;
+      table_id = stream->table_id;
   }
 
-  if (G_UNLIKELY (table_id == TABLE_ID_UNSET))
+  if (G_UNLIKELY (table_id == GST_MTS_TABLE_ID_UNSET))
     goto beach;
 
-  for (i = 0; si_tables[i] != TABLE_ID_UNSET; i++) {
+  for (i = 0; si_tables[i] != GST_MTS_TABLE_ID_UNSET; i++) {
     if (G_UNLIKELY (si_tables[i] == table_id)) {
       retval = TRUE;
       break;
@@ -815,19 +676,18 @@ invalid_pid:
   return FALSE;
 }
 
-static void
-mpegts_base_apply_pat (MpegTSBase * base, GstStructure * pat_info)
+static gboolean
+mpegts_base_apply_pat (MpegTSBase * base, GstMpegTSSection * section)
 {
-  const GValue *value;
-  GstStructure *old_pat;
-  GstStructure *program_info;
-  guint program_number;
-  guint pid;
+  GArray *pat = gst_mpegts_section_get_pat (section);
+  GArray *old_pat;
   MpegTSBaseProgram *program;
-  gint i, nbprograms;
-  const GValue *programs;
+  gint i;
 
-  GST_INFO_OBJECT (base, "PAT %" GST_PTR_FORMAT, pat_info);
+  if (G_UNLIKELY (pat == NULL))
+    return FALSE;
+
+  GST_INFO_OBJECT (base, "PAT");
 
   /* Applying a new PAT does two things:
    * * It adds the new programs to the list of programs this element handles
@@ -838,28 +698,17 @@ mpegts_base_apply_pat (MpegTSBase * base, GstStructure * pat_info)
    */
 
   old_pat = base->pat;
-  base->pat = pat_info;
-
-  gst_element_post_message (GST_ELEMENT_CAST (base),
-      gst_message_new_element (GST_OBJECT (base),
-          gst_structure_copy (pat_info)));
-
+  base->pat = pat;
 
   GST_LOG ("Activating new Program Association Table");
   /* activate the new table */
-  programs = gst_structure_id_get_value (pat_info, QUARK_PROGRAMS);
-  nbprograms = gst_value_list_get_size (programs);
-  for (i = 0; i < nbprograms; ++i) {
-    value = gst_value_list_get_value (programs, i);
-
-    program_info = g_value_get_boxed (value);
-    gst_structure_id_get (program_info, QUARK_PROGRAM_NUMBER, G_TYPE_UINT,
-        &program_number, QUARK_PID, G_TYPE_UINT, &pid, NULL);
+  for (i = 0; i < pat->len; ++i) {
+    GstMpegTSPatProgram *patp = &g_array_index (pat, GstMpegTSPatProgram, i);
 
-    program = mpegts_base_get_program (base, program_number);
+    program = mpegts_base_get_program (base, patp->program_number);
     if (program) {
       /* IF the program already existed, just check if the PMT PID changed */
-      if (program->pmt_pid != pid) {
+      if (program->pmt_pid != patp->network_or_program_map_PID) {
         if (program->pmt_pid != G_MAXUINT16) {
           /* pmt pid changed */
           /* FIXME: when this happens it may still be pmt pid of another
@@ -868,12 +717,18 @@ mpegts_base_apply_pat (MpegTSBase * base, GstStructure * pat_info)
           MPEGTS_BIT_UNSET (base->known_psi, program->pmt_pid);
         }
 
-        program->pmt_pid = pid;
-        MPEGTS_BIT_SET (base->known_psi, pid);
+        program->pmt_pid = patp->network_or_program_map_PID;
+        if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, program->pmt_pid)))
+          GST_FIXME
+              ("Refcounting issue. Setting twice a PMT PID (0x%04x) as know PSI",
+              program->pmt_pid);
+        MPEGTS_BIT_SET (base->known_psi, patp->network_or_program_map_PID);
       }
     } else {
       /* Create a new program */
-      program = mpegts_base_add_program (base, program_number, pid);
+      program =
+          mpegts_base_add_program (base, patp->program_number,
+          patp->network_or_program_map_PID);
     }
     /* We mark this program as being referenced by one PAT */
     program->patcount += 1;
@@ -883,20 +738,14 @@ mpegts_base_apply_pat (MpegTSBase * base, GstStructure * pat_info)
     /* deactivate the old table */
     GST_LOG ("Deactivating old Program Association Table");
 
-    programs = gst_structure_id_get_value (old_pat, QUARK_PROGRAMS);
-    nbprograms = gst_value_list_get_size (programs);
-    for (i = 0; i < nbprograms; ++i) {
-      value = gst_value_list_get_value (programs, i);
+    for (i = 0; i < old_pat->len; ++i) {
+      GstMpegTSPatProgram *patp =
+          &g_array_index (old_pat, GstMpegTSPatProgram, i);
 
-      program_info = g_value_get_boxed (value);
-      gst_structure_id_get (program_info,
-          QUARK_PROGRAM_NUMBER, G_TYPE_UINT, &program_number,
-          QUARK_PID, G_TYPE_UINT, &pid, NULL);
-
-      program = mpegts_base_get_program (base, program_number);
+      program = mpegts_base_get_program (base, patp->program_number);
       if (G_UNLIKELY (program == NULL)) {
         GST_DEBUG_OBJECT (base, "broken PAT, duplicated entry for program %d",
-            program_number);
+            patp->program_number);
         continue;
       }
 
@@ -904,43 +753,56 @@ mpegts_base_apply_pat (MpegTSBase * base, GstStructure * pat_info)
         /* the program has been referenced by the new pat, keep it */
         continue;
 
-      GST_INFO_OBJECT (base, "PAT removing program %" GST_PTR_FORMAT,
-          program_info);
+      GST_INFO_OBJECT (base, "PAT removing program 0x%04x 0x%04x",
+          patp->program_number, patp->network_or_program_map_PID);
 
       mpegts_base_deactivate_program (base, program);
-      mpegts_base_remove_program (base, program_number);
+      mpegts_base_remove_program (base, patp->program_number);
       /* FIXME: when this happens it may still be pmt pid of another
        * program, so setting to False may make it go through expensive
        * path in is_psi unnecessarily */
-      MPEGTS_BIT_SET (base->known_psi, pid);
-      mpegts_packetizer_remove_stream (base->packetizer, pid);
+      if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi,
+                  patp->network_or_program_map_PID))) {
+        GST_FIXME
+            ("Program refcounting : Setting twice a pid (0x%04x) as known PSI",
+            patp->network_or_program_map_PID);
+      }
+      MPEGTS_BIT_SET (base->known_psi, patp->network_or_program_map_PID);
+      mpegts_packetizer_remove_stream (base->packetizer,
+          patp->network_or_program_map_PID);
     }
 
-    gst_structure_free (old_pat);
+    g_array_unref (old_pat);
   }
+
+  return TRUE;
 }
 
-static void
-mpegts_base_apply_pmt (MpegTSBase * base,
-    guint16 pmt_pid, GstStructure * pmt_info)
+static gboolean
+mpegts_base_apply_pmt (MpegTSBase * base, GstMpegTSSection * section)
 {
+  const GstMpegTSPMT *pmt;
   MpegTSBaseProgram *program, *old_program;
   guint program_number;
   gboolean initial_program = TRUE;
 
+  pmt = gst_mpegts_section_get_pmt (section);
+  if (G_UNLIKELY (pmt == NULL)) {
+    GST_ERROR ("Could not get PMT (corrupted ?)");
+    return FALSE;
+  }
+
   /* FIXME : not so sure this is valid anymore */
   if (G_UNLIKELY (base->seen_pat == FALSE)) {
     GST_WARNING ("Got pmt without pat first. Returning");
     /* remove the stream since we won't get another PMT otherwise */
-    mpegts_packetizer_remove_stream (base->packetizer, pmt_pid);
-    return;
+    mpegts_packetizer_remove_stream (base->packetizer, section->pid);
+    return TRUE;
   }
 
-  gst_structure_id_get (pmt_info, QUARK_PROGRAM_NUMBER, G_TYPE_UINT,
-      &program_number, NULL);
-
+  program_number = section->subtable_extension;
   GST_DEBUG ("Applying PMT (program_number:%d, pid:0x%04x)",
-      program_number, pmt_pid);
+      program_number, section->pid);
 
   /* In order for stream switching to happen properly in decodebin(2),
    * we need to first add the new pads (i.e. activate the new program)
@@ -951,14 +813,14 @@ mpegts_base_apply_pmt (MpegTSBase * base,
   if (G_UNLIKELY (old_program == NULL))
     goto no_program;
 
-  if (G_UNLIKELY (mpegts_base_is_same_program (base, old_program, pmt_pid,
-              pmt_info)))
+  if (G_UNLIKELY (mpegts_base_is_same_program (base, old_program, section->pid,
+              pmt)))
     goto same_program;
 
   /* If the current program is active, this means we have a new program */
   if (old_program->active) {
     old_program = mpegts_base_steal_program (base, program_number);
-    program = mpegts_base_new_program (base, program_number, pmt_pid);
+    program = mpegts_base_new_program (base, program_number, section->pid);
     g_hash_table_insert (base->programs,
         GINT_TO_POINTER (program_number), program);
 
@@ -971,305 +833,110 @@ mpegts_base_apply_pmt (MpegTSBase * base,
 
   /* activate program */
   /* Ownership of pmt_info is given to the program */
-  mpegts_base_activate_program (base, program, pmt_pid, pmt_info,
+  mpegts_base_activate_program (base, program, section->pid, section, pmt,
       initial_program);
 
-  gst_element_post_message (GST_ELEMENT_CAST (base),
-      gst_message_new_element (GST_OBJECT (base),
-          gst_structure_copy (pmt_info)));
-
-  return;
+  return TRUE;
 
 no_program:
   {
     GST_ERROR ("Attempted to apply a PMT on a program that wasn't created");
-    gst_structure_free (pmt_info);
-    return;
+    return TRUE;
   }
 
 same_program:
   {
     GST_DEBUG ("Not applying identical program");
-    gst_structure_free (pmt_info);
-    return;
+    return TRUE;
   }
 }
 
 static void
-mpegts_base_apply_cat (MpegTSBase * base, GstStructure * cat_info)
-{
-  GST_DEBUG_OBJECT (base, "CAT %" GST_PTR_FORMAT, cat_info);
-
-  gst_element_post_message (GST_ELEMENT_CAST (base),
-      gst_message_new_element (GST_OBJECT (base), cat_info));
-}
-
-static void
-mpegts_base_apply_nit (MpegTSBase * base,
-    guint16 pmt_pid, GstStructure * nit_info)
+mpegts_base_handle_psi (MpegTSBase * base, GstMpegTSSection * section)
 {
-  GST_DEBUG_OBJECT (base, "NIT %" GST_PTR_FORMAT, nit_info);
-
-  gst_element_post_message (GST_ELEMENT_CAST (base),
-      gst_message_new_element (GST_OBJECT (base), nit_info));
-}
-
-static void
-mpegts_base_apply_sdt (MpegTSBase * base,
-    guint16 pmt_pid, GstStructure * sdt_info)
-{
-  GST_DEBUG_OBJECT (base, "SDT %" GST_PTR_FORMAT, sdt_info);
-
-  mpegts_base_get_tags_from_sdt (base, sdt_info);
-
-  gst_element_post_message (GST_ELEMENT_CAST (base),
-      gst_message_new_element (GST_OBJECT (base), sdt_info));
-}
-
-static void
-mpegts_base_apply_eit (MpegTSBase * base,
-    guint16 pmt_pid, GstStructure * eit_info)
-{
-  GST_DEBUG_OBJECT (base, "EIT %" GST_PTR_FORMAT, eit_info);
-
-  mpegts_base_get_tags_from_eit (base, eit_info);
-
-  gst_element_post_message (GST_ELEMENT_CAST (base),
-      gst_message_new_element (GST_OBJECT (base), eit_info));
-}
-
-static void
-mpegts_base_apply_tdt (MpegTSBase * base,
-    guint16 tdt_pid, GstStructure * tdt_info)
-{
-  gst_element_post_message (GST_ELEMENT_CAST (base),
-      gst_message_new_element (GST_OBJECT (base),
-          gst_structure_copy (tdt_info)));
-
-  GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base,
-      gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, tdt_info));
-}
-
-
-gboolean
-mpegts_base_handle_psi (MpegTSBase * base, MpegTSPacketizerSection * section)
-{
-  gboolean res = TRUE;
-  GstStructure *structure = NULL;
-
-  /* table ids 0x70 - 0x73 do not have a crc (EN 300 468) */
-  /* table ids 0x75 - 0x77 do not have a crc (TS 102 323) */
-  /* table id 0x7e does not have a crc (EN 300 468) */
-  /* table ids 0x80 - 0x8f do not have a crc (CA_message section ETR 289) */
-  if (G_LIKELY ((section->table_id < 0x70 || section->table_id > 0x73)
-          && (section->table_id < 0x75 || section->table_id > 0x77)
-          && (section->table_id < 0x80 || section->table_id > 0x8f)
-          && (section->table_id != 0x7e))) {
-    if (G_UNLIKELY (mpegts_base_calc_crc32 (section->data,
-                section->section_length) != 0)) {
-      GST_WARNING_OBJECT (base, "bad crc in psi pid 0x%04x (table_id:0x%02x)",
-          section->pid, section->table_id);
-      return FALSE;
-    }
-  }
+  gboolean post_message = TRUE;
 
   GST_DEBUG ("Handling PSI (pid: 0x%04x , table_id: 0x%02x)",
       section->pid, section->table_id);
 
-  switch (section->table_id) {
-    case TABLE_ID_PROGRAM_ASSOCIATION:
-      /* PAT */
-      structure = mpegts_packetizer_parse_pat (base->packetizer, section);
-      if (G_LIKELY (structure)) {
-        mpegts_base_apply_pat (base, structure);
-        if (base->seen_pat == FALSE) {
-          base->seen_pat = TRUE;
-          GST_DEBUG ("First PAT offset: %" G_GUINT64_FORMAT, section->offset);
-          mpegts_packetizer_set_reference_offset (base->packetizer,
-              section->offset);
-        }
-
-      } else
-        res = FALSE;
-
-      break;
-    case TABLE_ID_CONDITIONAL_ACCESS:
-      /* CAT */
-      structure = mpegts_packetizer_parse_cat (base->packetizer, section);
-      if (structure)
-        mpegts_base_apply_cat (base, structure);
-      else
-        res = FALSE;
-      break;
-    case TABLE_ID_TS_PROGRAM_MAP:
-      /* PMT */
-      structure = mpegts_packetizer_parse_pmt (base->packetizer, section);
-      if (G_LIKELY (structure))
-        mpegts_base_apply_pmt (base, section->pid, structure);
-      else
-        res = FALSE;
-
-      break;
-    case TABLE_ID_NETWORK_INFORMATION_ACTUAL_NETWORK:
-      /* NIT, actual network */
-    case TABLE_ID_NETWORK_INFORMATION_OTHER_NETWORK:
-      /* NIT, other network */
-      structure = mpegts_packetizer_parse_nit (base->packetizer, section);
-      if (G_LIKELY (structure))
-        mpegts_base_apply_nit (base, section->pid, structure);
-      else
-        res = FALSE;
-
-      break;
-    case TABLE_ID_SERVICE_DESCRIPTION_ACTUAL_TS:
-    case TABLE_ID_SERVICE_DESCRIPTION_OTHER_TS:
-      structure = mpegts_packetizer_parse_sdt (base->packetizer, section);
-      if (G_LIKELY (structure))
-        mpegts_base_apply_sdt (base, section->pid, structure);
-      else
-        res = FALSE;
-      break;
-    case 0x4E:
-    case 0x4F:
-      /* EIT, present/following */
-    case 0x50:
-    case 0x51:
-    case 0x52:
-    case 0x53:
-    case 0x54:
-    case 0x55:
-    case 0x56:
-    case 0x57:
-    case 0x58:
-    case 0x59:
-    case 0x5A:
-    case 0x5B:
-    case 0x5C:
-    case 0x5D:
-    case 0x5E:
-    case 0x5F:
-    case 0x60:
-    case 0x61:
-    case 0x62:
-    case 0x63:
-    case 0x64:
-    case 0x65:
-    case 0x66:
-    case 0x67:
-    case 0x68:
-    case 0x69:
-    case 0x6A:
-    case 0x6B:
-    case 0x6C:
-    case 0x6D:
-    case 0x6E:
-    case 0x6F:
-      /* EIT, schedule */
-      /* FIXME : Can take up to 50% of total mpeg-ts demuxing cpu usage ! */
-      structure = mpegts_packetizer_parse_eit (base->packetizer, section);
-      if (G_LIKELY (structure))
-        mpegts_base_apply_eit (base, section->pid, structure);
-      else
-        res = FALSE;
-      break;
-    case TABLE_ID_TIME_DATE:
-      /* TDT (Time and Date table) */
-      structure = mpegts_packetizer_parse_tdt (base->packetizer, section);
-      if (G_LIKELY (structure))
-        mpegts_base_apply_tdt (base, section->pid, structure);
-      else
-        res = FALSE;
+  switch (section->section_type) {
+    case GST_MPEGTS_SECTION_PAT:
+      post_message = mpegts_base_apply_pat (base, section);
+      if (base->seen_pat == FALSE) {
+        base->seen_pat = TRUE;
+        GST_DEBUG ("First PAT offset: %" G_GUINT64_FORMAT, section->offset);
+        mpegts_packetizer_set_reference_offset (base->packetizer,
+            section->offset);
+        break;
+      }
+    case GST_MPEGTS_SECTION_PMT:
+      post_message = mpegts_base_apply_pmt (base, section);
       break;
-    case TABLE_ID_TIME_OFFSET:
-      /* TOT (Time Offset table) */
-      structure = mpegts_packetizer_parse_tot (base->packetizer, section);
-      if (G_LIKELY (structure))
-        mpegts_base_apply_tdt (base, section->pid, structure);
-      else
-        res = FALSE;
+    case GST_MPEGTS_SECTION_EIT:
+      /* some tag xtraction + posting */
+      post_message = mpegts_base_get_tags_from_eit (base, section);
       break;
     default:
-      GST_WARNING ("Unhandled or unknown section type (table_id 0x%02x)",
-          section->table_id);
       break;
   }
 
-  return res;
+  /* Finally post message (if it wasn't corrupted) */
+  if (post_message)
+    gst_element_post_message (GST_ELEMENT_CAST (base),
+        gst_message_new_mpegts_section (GST_OBJECT (base), section));
+  gst_mpegts_section_unref (section);
 }
 
-static void
-mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info)
-{
-  const GValue *services;
-  guint i;
 
-  services = gst_structure_get_value (sdt_info, "services");
-
-  for (i = 0; i < gst_value_list_get_size (services); i++) {
-    const GstStructure *service;
-    const gchar *sid_str;
-    gchar *tmp;
-    gint program_number;
-    MpegTSBaseProgram *program;
-
-    service = gst_value_get_structure (gst_value_list_get_value (services, i));
-
-    /* get program_number from structure name
-     * which looks like service-%d */
-    sid_str = gst_structure_get_name (service);
-    tmp = g_strstr_len (sid_str, -1, "-");
-    if (!tmp)
-      continue;
-    program_number = atoi (++tmp);
-
-    program = mpegts_base_get_program (base, program_number);
-    if (program && !program->tags) {
-      program->tags = gst_tag_list_new (GST_TAG_ARTIST,
-          gst_structure_get_string (service, "name"), NULL);
-    }
-  }
-}
-
-static void
-mpegts_base_get_tags_from_eit (MpegTSBase * base, GstStructure * eit_info)
+static gboolean
+mpegts_base_get_tags_from_eit (MpegTSBase * base, GstMpegTSSection * section)
 {
-  const GValue *events;
+  const GstMpegTSEIT *eit;
   guint i;
-  guint program_number;
   MpegTSBaseProgram *program;
-  gboolean present_following;
-
-  gst_structure_get_uint (eit_info, "service-id", &program_number);
-  program = mpegts_base_get_program (base, program_number);
-
-  gst_structure_get_boolean (eit_info, "present-following", &present_following);
-
-  if (program && present_following) {
-    events = gst_structure_get_value (eit_info, "events");
-
-    for (i = 0; i < gst_value_list_get_size (events); i++) {
-      const GstStructure *event;
-      const gchar *title;
-      guint status;
-      guint event_id;
-      guint duration;
 
-      event = gst_value_get_structure (gst_value_list_get_value (events, i));
+  /* Early exit if it's not from the present/following table_id */
+  if (section->table_id != GST_MTS_TABLE_ID_EVENT_INFORMATION_ACTUAL_TS_PRESENT
+      || section->table_id !=
+      GST_MTS_TABLE_ID_EVENT_INFORMATION_OTHER_TS_PRESENT)
+    return TRUE;
 
-      title = gst_structure_get_string (event, "name");
-      gst_structure_get_uint (event, "event-id", &event_id);
-      gst_structure_get_uint (event, "running-status", &status);
-
-      if (title && event_id != program->event_id
-          && status == RUNNING_STATUS_RUNNING) {
-        gst_structure_get_uint (event, "duration", &duration);
+  eit = gst_mpegts_section_get_eit (section);
+  if (G_UNLIKELY (eit == NULL))
+    return FALSE;
 
-        program->event_id = event_id;
-        program->tags = gst_tag_list_new (GST_TAG_TITLE,
-            title, GST_TAG_DURATION, duration * GST_SECOND, NULL);
+  program = mpegts_base_get_program (base, section->subtable_extension);
+
+  GST_DEBUG
+      ("program_id:0x%04x, table_id:0x%02x, actual_stream:%d, present_following:%d, program:%p",
+      section->subtable_extension, section->table_id, eit->actual_stream,
+      eit->present_following, program);
+
+  if (program && eit->present_following) {
+    for (i = 0; i < eit->events->len; i++) {
+      GstMpegTSEITEvent *event = g_ptr_array_index (eit->events, i);
+      const GstMpegTSDescriptor *desc;
+
+      if (event->running_status == RUNNING_STATUS_RUNNING) {
+        program->event_id = event->event_id;
+        if ((desc =
+                gst_mpegts_find_descriptor (event->descriptors,
+                    GST_MTS_DESC_DVB_SHORT_EVENT))) {
+          gchar *name;
+          if (gst_mpegts_descriptor_parse_dvb_short_event (desc, NULL, &name,
+                  NULL)) {
+            /* FIXME : Is it correct to post an event duration as a GST_TAG_DURATION ??? */
+            program->tags =
+                gst_tag_list_new (GST_TAG_TITLE, name, GST_TAG_DURATION,
+                event->duration * GST_SECOND, NULL);
+            return TRUE;
+          }
+        }
       }
     }
   }
+
+  return TRUE;
 }
 
 static gboolean
@@ -1372,7 +1039,6 @@ mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
   GstFlowReturn res = GST_FLOW_OK;
   MpegTSBase *base;
-  gboolean based;
   MpegTSPacketizerPacketReturn pret;
   MpegTSPacketizer2 *packetizer;
   MpegTSPacketizerPacket packet;
@@ -1405,29 +1071,16 @@ mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
       goto next;
     }
 
-    /* FIXME : Handle the case where we have multiple sections in one
-     * packet ! 
-     * See bug #677443
-     */
     /* base PSI data */
     if (packet.payload != NULL && mpegts_base_is_psi (base, &packet)) {
-      MpegTSPacketizerSection section;
-      based = mpegts_packetizer_push_section (packetizer, &packet, &section);
-      if (G_UNLIKELY (!based))
-        /* bad section data */
-        goto next;
-
-      if (G_LIKELY (section.complete)) {
-        /* section complete */
-        based = mpegts_base_handle_psi (base, &section);
-
-        if (G_UNLIKELY (!based)) {
-          /* bad PSI table */
-          goto next;
-        }
-      }
+      GstMpegTSSection *section;
+
+      section = mpegts_packetizer_push_section (packetizer, &packet);
+      if (section)
+        mpegts_base_handle_psi (base, section);
+
       /* we need to push section packet downstream */
-      res = klass->push (base, &packet, &section);
+      res = klass->push (base, &packet, section);
 
     } else if (MPEGTS_BIT_IS_SET (base->is_pes, packet.pid)) {
       /* push the packet downstream */
@@ -1810,7 +1463,5 @@ gst_mpegtsbase_plugin_init (GstPlugin * plugin)
   GST_DEBUG_CATEGORY_INIT (mpegts_base_debug, "mpegtsbase", 0,
       "MPEG transport stream base class");
 
-  gst_mpegtsdesc_init_debug ();
-
   return TRUE;
 }
index 83c0c94..759264d 100644 (file)
@@ -59,7 +59,7 @@ struct _MpegTSBaseStream
 {
   guint16 pid;
   guint8 stream_type;
-  GstStructure* stream_info;
+  GstMpegTSPMTStream *stream;
 };
 
 struct _MpegTSBaseProgram
@@ -67,7 +67,8 @@ struct _MpegTSBaseProgram
   gint program_number;
   guint16 pmt_pid;
   guint16 pcr_pid;
-  GstStructure *pmt_info;
+  GstMpegTSSection *section;
+  const GstMpegTSPMT *pmt;
   MpegTSBaseStream **streams;
   GList *stream_list;
   gint patcount;
@@ -110,7 +111,7 @@ struct _MpegTSBase {
    * accessed from the application thread and the streaming thread */
   GHashTable *programs;
 
-  GstStructure *pat;
+  GArray  *pat;
   MpegTSPacketizer2 *packetizer;
 
   /* arrays that say whether a pid is a known psi pid or a pes pid */
@@ -145,7 +146,7 @@ struct _MpegTSBaseClass {
 
   /* Virtual methods */
   void (*reset) (MpegTSBase *base);
-  GstFlowReturn (*push) (MpegTSBase *base, MpegTSPacketizerPacket *packet, MpegTSPacketizerSection * section);
+  GstFlowReturn (*push) (MpegTSBase *base, MpegTSPacketizerPacket *packet, GstMpegTSSection * section);
   /* takes ownership of @event */
   gboolean (*push_event) (MpegTSBase *base, GstEvent * event);
 
@@ -190,16 +191,14 @@ G_GNUC_INTERNAL GType mpegts_base_get_type(void);
 G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_get_program (MpegTSBase * base, gint program_number);
 G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_add_program (MpegTSBase * base, gint program_number, guint16 pmt_pid);
 
-G_GNUC_INTERNAL guint8 *mpegts_get_descriptor_from_stream (MpegTSBaseStream * stream, guint8 tag);
-G_GNUC_INTERNAL guint8 *mpegts_get_descriptor_from_program (MpegTSBaseProgram * program, guint8 tag);
+G_GNUC_INTERNAL const guint8 *mpegts_get_descriptor_from_stream (MpegTSBaseStream * stream, guint8 tag);
+G_GNUC_INTERNAL const guint8 *mpegts_get_descriptor_from_program (MpegTSBaseProgram * program, guint8 tag);
 
 G_GNUC_INTERNAL gboolean
 mpegts_base_handle_seek_event(MpegTSBase * base, GstPad * pad, GstEvent * event);
 
 G_GNUC_INTERNAL gboolean gst_mpegtsbase_plugin_init (GstPlugin * plugin);
 
-G_GNUC_INTERNAL gboolean mpegts_base_handle_psi (MpegTSBase * base, MpegTSPacketizerSection * section);
-
 G_GNUC_INTERNAL void mpegts_base_program_remove_stream (MpegTSBase * base, MpegTSBaseProgram * program, guint16 pid);
 
 G_GNUC_INTERNAL void mpegts_base_remove_program(MpegTSBase *base, gint program_number);
index 63da033..37562c3 100644 (file)
  */
 
 #include <string.h>
-
-/* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
+#include <stdlib.h>
 
 /* Skew calculation pameters */
 #define MAX_TIME       (2 * GST_SECOND)
 GST_DEBUG_CATEGORY_STATIC (mpegts_packetizer_debug);
 #define GST_CAT_DEFAULT mpegts_packetizer_debug
 
-static GQuark QUARK_PAT;
-static GQuark QUARK_TRANSPORT_STREAM_ID;
-static GQuark QUARK_PROGRAM_NUMBER;
-static GQuark QUARK_PID;
-static GQuark QUARK_PROGRAMS;
-
-static GQuark QUARK_CAT;
-
-static GQuark QUARK_PMT;
-static GQuark QUARK_PCR_PID;
-static GQuark QUARK_VERSION_NUMBER;
-static GQuark QUARK_DESCRIPTORS;
-static GQuark QUARK_STREAM_TYPE;
-static GQuark QUARK_STREAMS;
-
-static GQuark QUARK_NIT;
-static GQuark QUARK_NETWORK_ID;
-static GQuark QUARK_CURRENT_NEXT_INDICATOR;
-static GQuark QUARK_ACTUAL_NETWORK;
-static GQuark QUARK_NETWORK_NAME;
-static GQuark QUARK_ORIGINAL_NETWORK_ID;
-static GQuark QUARK_TRANSPORTS;
-static GQuark QUARK_TERRESTRIAL;
-static GQuark QUARK_CABLE;
-static GQuark QUARK_FREQUENCY;
-static GQuark QUARK_MODULATION;
-static GQuark QUARK_BANDWIDTH;
-static GQuark QUARK_CONSTELLATION;
-static GQuark QUARK_HIERARCHY;
-static GQuark QUARK_CODE_RATE_HP;
-static GQuark QUARK_CODE_RATE_LP;
-static GQuark QUARK_GUARD_INTERVAL;
-static GQuark QUARK_TRANSMISSION_MODE;
-static GQuark QUARK_OTHER_FREQUENCY;
-static GQuark QUARK_SYMBOL_RATE;
-static GQuark QUARK_INNER_FEC;
-static GQuark QUARK_DELIVERY;
-static GQuark QUARK_CHANNELS;
-static GQuark QUARK_LOGICAL_CHANNEL_NUMBER;
-
-static GQuark QUARK_SDT;
-static GQuark QUARK_ACTUAL_TRANSPORT_STREAM;
-static GQuark QUARK_SERVICES;
-
-static GQuark QUARK_EIT;
-static GQuark QUARK_SERVICE_ID;
-static GQuark QUARK_PRESENT_FOLLOWING;
-static GQuark QUARK_SEGMENT_LAST_SECTION_NUMBER;
-static GQuark QUARK_LAST_TABLE_ID;
-static GQuark QUARK_EVENTS;
-static GQuark QUARK_NAME;
-static GQuark QUARK_DESCRIPTION;
-static GQuark QUARK_EXTENDED_ITEM;
-static GQuark QUARK_EXTENDED_ITEMS;
-static GQuark QUARK_TEXT;
-static GQuark QUARK_EXTENDED_TEXT;
-static GQuark QUARK_EVENT_ID;
-static GQuark QUARK_YEAR;
-static GQuark QUARK_MONTH;
-static GQuark QUARK_DAY;
-static GQuark QUARK_HOUR;
-static GQuark QUARK_MINUTE;
-static GQuark QUARK_SECOND;
-static GQuark QUARK_DURATION;
-static GQuark QUARK_RUNNING_STATUS;
-static GQuark QUARK_FREE_CA_MODE;
-
-static GQuark QUARK_TDT;
-static GQuark QUARK_TOT;
-
-#define MAX_KNOWN_ICONV 25
-/* All these conversions will be to UTF8 */
-typedef enum
-{
-  _ICONV_UNKNOWN = -1,
-  _ICONV_ISO8859_1,
-  _ICONV_ISO8859_2,
-  _ICONV_ISO8859_3,
-  _ICONV_ISO8859_4,
-  _ICONV_ISO8859_5,
-  _ICONV_ISO8859_6,
-  _ICONV_ISO8859_7,
-  _ICONV_ISO8859_8,
-  _ICONV_ISO8859_9,
-  _ICONV_ISO8859_10,
-  _ICONV_ISO8859_11,
-  _ICONV_ISO8859_12,
-  _ICONV_ISO8859_13,
-  _ICONV_ISO8859_14,
-  _ICONV_ISO8859_15,
-  _ICONV_ISO10646_UC2,
-  _ICONV_EUC_KR,
-  _ICONV_GB2312,
-  _ICONV_UTF_16BE,
-  _ICONV_ISO10646_UTF8,
-  _ICONV_ISO6937,
-  /* Insert more here if needed */
-  _ICONV_MAX
-} LocalIconvCode;
-
-static const gchar *iconvtablename[] = {
-  "iso-8859-1",
-  "iso-8859-2",
-  "iso-8859-3",
-  "iso-8859-4",
-  "iso-8859-5",
-  "iso-8859-6",
-  "iso-8859-7",
-  "iso-8859-8",
-  "iso-8859-9",
-  "iso-8859-10",
-  "iso-8859-11",
-  "iso-8859-12",
-  "iso-8859-13",
-  "iso-8859-14",
-  "iso-8859-15",
-  "ISO-10646/UCS2",
-  "EUC-KR",
-  "GB2312",
-  "UTF-16BE",
-  "ISO-10646/UTF8",
-  "iso6937"
-      /* Insert more here if needed */
-};
-
 #define MPEGTS_PACKETIZER_GET_PRIVATE(obj)  \
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_MPEGTS_PACKETIZER, MpegTSPacketizerPrivate))
 
@@ -231,27 +103,21 @@ struct _MpegTSPacketizerPrivate
   guint8 pcrtablelut[0x2000];
   MpegTSPCR *observations[MAX_PCR_OBS_CHANNELS];
   guint8 lastobsid;
-
-  /* Conversion tables */
-  GIConv iconvs[_ICONV_MAX];
 };
 
 static void mpegts_packetizer_dispose (GObject * object);
 static void mpegts_packetizer_finalize (GObject * object);
-static gchar *get_encoding_and_convert (MpegTSPacketizer2 * packetizer,
-    const gchar * text, guint length);
 static GstClockTime calculate_skew (MpegTSPCR * pcr, guint64 pcrtime,
     GstClockTime time);
 static void record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable,
     guint64 pcr, guint64 offset);
 
 #define CONTINUITY_UNSET 255
-#define MAX_CONTINUITY 15
 #define VERSION_NUMBER_UNSET 255
 #define TABLE_ID_UNSET 0xFF
 #define PACKET_SYNC_BYTE 0x47
 
-static MpegTSPCR *
+static inline MpegTSPCR *
 get_pcr_table (MpegTSPacketizer2 * packetizer, guint16 pid)
 {
   MpegTSPacketizerPrivate *priv = packetizer->priv;
@@ -311,6 +177,7 @@ find_subtable (GSList * subtables, guint8 table_id, guint16 subtable_extension)
 {
   GSList *tmp;
 
+  /* FIXME: Make this an array ! */
   for (tmp = subtables; tmp; tmp = tmp->next) {
     MpegTSPacketizerStreamSubtable *sub =
         (MpegTSPacketizerStreamSubtable *) tmp->data;
@@ -323,20 +190,35 @@ find_subtable (GSList * subtables, guint8 table_id, guint16 subtable_extension)
 }
 
 static gboolean
-saw_subtable_crc (GList * list, guint32 crc)
+seen_section_before (MpegTSPacketizerStream * stream, guint8 table_id,
+    guint16 subtable_extension, guint8 version_number, guint8 section_number,
+    guint8 last_section_number)
 {
-  GList *tmp;
-
-  for (tmp = list; tmp; tmp = tmp->next)
-    if (GPOINTER_TO_UINT (tmp->data) == crc)
-      return TRUE;
+  MpegTSPacketizerStreamSubtable *subtable;
 
-  return FALSE;
+  /* Check if we've seen this table_id/subtable_extension first */
+  subtable = find_subtable (stream->subtables, table_id, subtable_extension);
+  if (!subtable) {
+    GST_DEBUG ("Haven't seen subtale");
+    return FALSE;
+  }
+  /* If we have, check it has the same version_number */
+  if (subtable->version_number != version_number) {
+    GST_DEBUG ("Different version number");
+    return FALSE;
+  }
+  /* Did the number of sections change ? */
+  if (subtable->last_section_number != last_section_number) {
+    GST_DEBUG ("Different last_section_number");
+    return FALSE;
+  }
+  /* Finally return whether we saw that section or not */
+  return MPEGTS_BIT_IS_SET (subtable->seen_section, section_number);
 }
 
 static MpegTSPacketizerStreamSubtable *
 mpegts_packetizer_stream_subtable_new (guint8 table_id,
-    guint16 subtable_extension)
+    guint16 subtable_extension, guint8 last_section_number)
 {
   MpegTSPacketizerStreamSubtable *subtable;
 
@@ -344,19 +226,20 @@ mpegts_packetizer_stream_subtable_new (guint8 table_id,
   subtable->version_number = VERSION_NUMBER_UNSET;
   subtable->table_id = table_id;
   subtable->subtable_extension = subtable_extension;
-  subtable->crc = NULL;
+  subtable->last_section_number = last_section_number;
   return subtable;
 }
 
 static MpegTSPacketizerStream *
-mpegts_packetizer_stream_new (void)
+mpegts_packetizer_stream_new (guint16 pid)
 {
   MpegTSPacketizerStream *stream;
 
   stream = (MpegTSPacketizerStream *) g_new0 (MpegTSPacketizerStream, 1);
   stream->continuity_counter = CONTINUITY_UNSET;
   stream->subtables = NULL;
-  stream->section_table_id = TABLE_ID_UNSET;
+  stream->table_id = TABLE_ID_UNSET;
+  stream->pid = pid;
   return stream;
 }
 
@@ -366,14 +249,16 @@ mpegts_packetizer_clear_section (MpegTSPacketizerStream * stream)
   stream->continuity_counter = CONTINUITY_UNSET;
   stream->section_length = 0;
   stream->section_offset = 0;
-  stream->section_table_id = TABLE_ID_UNSET;
+  stream->table_id = TABLE_ID_UNSET;
+  if (stream->section_data)
+    g_free (stream->section_data);
+  stream->section_data = NULL;
 }
 
 static void
 mpegts_packetizer_stream_subtable_free (MpegTSPacketizerStreamSubtable *
     subtable)
 {
-  g_list_free (subtable->crc);
   g_free (subtable);
 }
 
@@ -406,7 +291,6 @@ static void
 mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
 {
   MpegTSPacketizerPrivate *priv;
-  guint i;
 
   priv = packetizer->priv = MPEGTS_PACKETIZER_GET_PRIVATE (packetizer);
   packetizer->adapter = gst_adapter_new ();
@@ -424,9 +308,6 @@ mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
 
   memset (priv->pcrtablelut, 0xff, 0x200);
   memset (priv->observations, 0x0, sizeof (priv->observations));
-  for (i = 0; i < _ICONV_MAX; i++)
-    priv->iconvs[i] = (GIConv) - 1;
-
   priv->lastobsid = 0;
 
   priv->nb_seen_offsets = 0;
@@ -438,7 +319,6 @@ static void
 mpegts_packetizer_dispose (GObject * object)
 {
   MpegTSPacketizer2 *packetizer = GST_MPEGTS_PACKETIZER (object);
-  guint i;
 
   if (!packetizer->disposed) {
     if (packetizer->know_packet_size && packetizer->caps != NULL) {
@@ -461,10 +341,6 @@ mpegts_packetizer_dispose (GObject * object)
     packetizer->offset = 0;
     packetizer->empty = TRUE;
 
-    for (i = 0; i < _ICONV_MAX; i++)
-      if (packetizer->priv->iconvs[i] != (GIConv) - 1)
-        g_iconv_close (packetizer->priv->iconvs[i]);
-
     flush_observations (packetizer);
   }
 
@@ -510,15 +386,15 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 *
     return TRUE;
   }
 
-  if (packet->adaptation_field_control == 0x20) {
+  if (FLAGS_HAS_AFC (packet->scram_afc_cc)) {
     /* no payload, adaptation field of 183 bytes */
     if (length != 183) {
-      GST_DEBUG ("PID %d afc == 0x%x and length %d != 183",
-          packet->pid, packet->adaptation_field_control, length);
+      GST_DEBUG ("PID %d afc == 0x%02x and length %d != 183",
+          packet->pid, packet->scram_afc_cc & 0x30, length);
     }
   } else if (length > 182) {
-    GST_DEBUG ("PID %d afc == 0x%01x and length %d > 182",
-        packet->pid, packet->adaptation_field_control, length);
+    GST_DEBUG ("PID %d afc == 0x%02x and length %d > 182",
+        packet->pid, packet->scram_afc_cc & 0x30, length);
   }
 
   if (packet->data + length > packet->data_end) {
@@ -587,25 +463,18 @@ mpegts_packetizer_parse_packet (MpegTSPacketizer2 * packetizer,
   packet->pid = GST_READ_UINT16_BE (data) & 0x1FFF;
   data += 2;
 
-  tmp = *data;
+  packet->scram_afc_cc = tmp = *data++;
   /* transport_scrambling_control 2 */
   if (G_UNLIKELY (tmp & 0xc0))
     return PACKET_BAD;
 
-  /* adaptation_field_control 2 */
-  packet->adaptation_field_control = tmp & 0x30;
-
-  /* continuity_counter 4 */
-  packet->continuity_counter = tmp & 0x0F;
-  data += 1;
-
   packet->data = data;
 
-  if (packet->adaptation_field_control & 0x20)
+  if (FLAGS_HAS_AFC (tmp))
     if (!mpegts_packetizer_parse_adaptation_field_control (packetizer, packet))
       return FALSE;
 
-  if (packet->adaptation_field_control & 0x10)
+  if (FLAGS_HAS_PAYLOAD (tmp))
     packet->payload = packet->data;
   else
     packet->payload = NULL;
@@ -613,2090 +482,277 @@ mpegts_packetizer_parse_packet (MpegTSPacketizer2 * packetizer,
   return PACKET_OK;
 }
 
-static gboolean
+static GstMpegTSSection *
 mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerStream * stream, MpegTSPacketizerSection * section)
+    MpegTSPacketizerStream * stream)
 {
-  guint8 tmp;
-  guint8 *data, *crc_data;
   MpegTSPacketizerStreamSubtable *subtable;
-
-  section->complete = TRUE;
-  /* get the section buffer, ownership stays with the stream */
-  data = section->data = stream->section_data;
-  section->offset = stream->offset;
-
-  GST_MEMDUMP ("section header", data, stream->section_length);
-
-  /* table_id : 8 bits
-   * NOTE : Already parsed/stored in _push_section()
-   */
-  section->table_id = stream->section_table_id;
-  data += 1;
-
-  /* section_syntax_indicator :  1 bit
-   * private_indicator        :  1 bit
-   * RESERVED                 :  2 bit
-   * private_section_length   : 12 bit
-   */
-  /* if table_id is 0 (pat) then ignore the subtable extension */
-  if ((data[0] & 0x80) == 0 || section->table_id == 0)
-    section->subtable_extension = 0;
-  else
-    section->subtable_extension = GST_READ_UINT16_BE (data + 2);
+  GstMpegTSSection *res;
 
   subtable =
-      find_subtable (stream->subtables, section->table_id,
-      section->subtable_extension);
+      find_subtable (stream->subtables, stream->table_id,
+      stream->subtable_extension);
   if (subtable) {
-    GST_DEBUG ("Found previous subtable_extension:%d",
-        section->subtable_extension);
+    GST_DEBUG ("Found previous subtable_extension:0x%04x",
+        stream->subtable_extension);
+    if (G_UNLIKELY (stream->version_number != subtable->version_number)) {
+      /* If the version number changed, reset the subtable */
+      subtable->version_number = stream->version_number;
+      subtable->last_section_number = stream->last_section_number;
+      memset (subtable->seen_section, 0, 32);
+    }
   } else {
-    GST_DEBUG ("Appending new subtable_extension:%d",
-        section->subtable_extension);
-    subtable = mpegts_packetizer_stream_subtable_new (section->table_id,
-        section->subtable_extension);
-
+    GST_DEBUG ("Appending new subtable_extension: 0x%04x",
+        stream->subtable_extension);
+    subtable = mpegts_packetizer_stream_subtable_new (stream->table_id,
+        stream->subtable_extension, stream->last_section_number);
+    subtable->version_number = stream->version_number;
 
     stream->subtables = g_slist_prepend (stream->subtables, subtable);
   }
 
-  /* private_section_length : 12 bit
-   * NOTE : Already parsed/stored in _push_section()
-   * NOTE : Same as private_section_length mentionned above
-   */
-  section->section_length = stream->section_length;
-  data += 2;
-
-  /* transport_stream_id    : 16 bit */
-  /* skip to the version byte */
-  data += 2;
-
-  /* Reserved               :  2 bits
-   * version_number         :  5 bits
-   * current_next_indicator : 1 bit*/
-  tmp = *data++;
-  section->version_number = (tmp >> 1) & 0x1F;
-  section->current_next_indicator = tmp & 0x01;
-
-  if (!section->current_next_indicator)
-    goto not_applicable;
-
-  /* CRC is at the end of the section */
-  crc_data = section->data + section->section_length - 4;
-  section->crc = GST_READ_UINT32_BE (crc_data);
-
-  /* If the section version number hasn't changed and we have
-   * already seen this exact section before, don't process further
-   */
-  if (section->version_number == subtable->version_number &&
-      saw_subtable_crc (subtable->crc, section->crc))
-    goto no_changes;
-
-  /* If the version number changed, reset our observations */
-  if (section->version_number != subtable->version_number)
-    g_list_free (subtable->crc);
-
-  GST_DEBUG
-      ("section changed. pid 0x%04x table_id 0x%03x subtable_extension %d version number:%d (previous%d) crc 0x%x",
-      section->pid, section->table_id, section->subtable_extension,
-      section->version_number, subtable->version_number, section->crc);
-
-  subtable->version_number = section->version_number;
-  subtable->crc =
-      g_list_prepend (subtable->crc, GUINT_TO_POINTER (section->crc));
-  stream->section_table_id = section->table_id;
-
-  return TRUE;
+  GST_MEMDUMP ("Full section data", stream->section_data,
+      stream->section_length);
+  /* TODO ? : Replace this by an efficient version (where we provide all
+   * pre-parsed header data) */
+  res =
+      gst_mpegts_section_new (stream->pid, stream->section_data,
+      stream->section_allocated);
+  stream->section_data = NULL;
 
-no_changes:
-  GST_LOG
-      ("no changes. pid 0x%04x table_id 0x%02x subtable_extension %d, current_next %d version %d, crc 0x%x",
-      section->pid, section->table_id, section->subtable_extension,
-      section->current_next_indicator, section->version_number, section->crc);
-  section->complete = FALSE;
-  return TRUE;
+  if (res) {
+    /* NOTE : Due to the new mpegts-si system, There is a insanely low probability
+     * that we might have gotten a section that was corrupted (i.e. wrong crc)
+     * and that we consider it as seen.
+     *
+     * The reason why we consider this as acceptable is because all the previous
+     * checks were already done:
+     * * transport layer checks (DVB)
+     * * 0x47 validation
+     * * continuity counter validation
+     * * subtable validation
+     * * section_number validation
+     * * section_length validation
+     *
+     * The probability of this happening vs the overhead of doing CRC checks
+     * on all sections (including those we would not use) is just not worth it.
+     * */
+    MPEGTS_BIT_SET (subtable->seen_section, stream->section_number);
+    res->offset = stream->offset;
+  }
 
-not_applicable:
-  GST_LOG
-      ("not applicable pid 0x%04x table_id 0x%02x subtable_extension %d, current_next %d version %d, crc 0x%x",
-      section->pid, section->table_id, section->subtable_extension,
-      section->current_next_indicator, section->version_number, section->crc);
-  section->complete = FALSE;
-  return TRUE;
+  return res;
 }
 
-static inline void
-set_descriptors_array_on_structure (GstStructure * structure, GQuark quark,
-    GValueArray * descriptors)
+void
+mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer)
 {
-  GValue value = { 0 };
+  if (packetizer->know_packet_size) {
+    packetizer->know_packet_size = FALSE;
+    packetizer->packet_size = 0;
+    if (packetizer->caps != NULL) {
+      gst_caps_unref (packetizer->caps);
+      packetizer->caps = NULL;
+    }
+  }
+  if (packetizer->streams) {
+    int i;
+    for (i = 0; i < 8192; i++) {
+      if (packetizer->streams[i]) {
+        mpegts_packetizer_stream_free (packetizer->streams[i]);
+      }
+    }
+    memset (packetizer->streams, 0, 8192 * sizeof (MpegTSPacketizerStream *));
+  }
 
-  g_value_init (&value, G_TYPE_VALUE_ARRAY);
-  g_value_take_boxed (&value, descriptors);
-  gst_structure_id_take_value (structure, quark, &value);
+  gst_adapter_clear (packetizer->adapter);
+  packetizer->offset = 0;
+  packetizer->empty = TRUE;
+  packetizer->priv->available = 0;
+  packetizer->priv->mapped = NULL;
+  packetizer->priv->mapped_size = 0;
+  packetizer->priv->offset = 0;
+  packetizer->priv->last_in_time = GST_CLOCK_TIME_NONE;
 }
 
-static GValueArray *
-mpegts_packetizer_parse_descriptors (MpegTSPacketizer2 * packetizer,
-    guint8 ** buffer, guint8 * buffer_end)
+void
+mpegts_packetizer_flush (MpegTSPacketizer2 * packetizer, gboolean hard)
 {
-  GValueArray *descriptors = NULL;
-  guint8 length;
-  guint8 *data;
-  GString *desc;
-  guint i, nb_desc = 0;
-
-  data = *buffer;
-
-  while (data < buffer_end) {
-    data++;                     /* skip tag */
-    length = *data++;
+  GST_DEBUG ("Flushing");
 
-    if (data + length > buffer_end) {
-      GST_WARNING ("invalid descriptor length %d now at %d max %d", length,
-          (gint) (data - *buffer), (gint) (buffer_end - *buffer));
-      goto error;
+  if (packetizer->streams) {
+    int i;
+    for (i = 0; i < 8192; i++) {
+      if (packetizer->streams[i]) {
+        mpegts_packetizer_clear_section (packetizer->streams[i]);
+      }
     }
-
-    data += length;
-    nb_desc++;
   }
+  gst_adapter_clear (packetizer->adapter);
 
-  if (data != buffer_end) {
-    GST_WARNING ("descriptors size %d expected %d", (gint) (data - *buffer),
-        (gint) (buffer_end - *buffer));
-    goto error;
+  packetizer->offset = 0;
+  packetizer->empty = TRUE;
+  packetizer->priv->available = 0;
+  packetizer->priv->mapped = NULL;
+  packetizer->priv->offset = 0;
+  packetizer->priv->mapped_size = 0;
+  packetizer->priv->last_in_time = GST_CLOCK_TIME_NONE;
+  if (hard) {
+    /* For pull mode seeks in tsdemux the observation must be preserved */
+    flush_observations (packetizer);
   }
+}
 
-  data = *buffer;
-  descriptors = g_value_array_new (nb_desc);
-
-  for (i = 0; i < nb_desc; i++) {
-    GValue *value = &(descriptors->values[i]);
-    data++;                     /* skip tag */
-    length = *data++;
-
-    /* include length */
-    desc = g_string_new_len ((gchar *) data - 2, length + 2);
-    data += length;
-    /* G_TYPE_GSTRING is a GBoxed type and is used so properly marshalled from python */
-    g_value_init (value, G_TYPE_GSTRING);
-    g_value_take_boxed (value, desc);
+void
+mpegts_packetizer_remove_stream (MpegTSPacketizer2 * packetizer, gint16 pid)
+{
+  MpegTSPacketizerStream *stream = packetizer->streams[pid];
+  if (stream) {
+    GST_INFO ("Removing stream for PID %d", pid);
+    mpegts_packetizer_stream_free (stream);
+    packetizer->streams[pid] = NULL;
   }
-
-  descriptors->n_values = nb_desc;
-
-  *buffer = data;
-
-  return descriptors;
-
-error:
-  return NULL;
 }
 
-GstStructure *
-mpegts_packetizer_parse_cat (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
+MpegTSPacketizer2 *
+mpegts_packetizer_new (void)
 {
-  GstStructure *cat_info = NULL;
-  guint8 *data;
-  guint8 tmp;
-  GValueArray *descriptors;
-  GstMPEGDescriptor desc;
-  guint desc_len;
-
-  /* Skip parts already parsed */
-  data = section->data + 3;
-
-  /* reserved  : 18bits */
-  data += 2;
-
-  /* version_number         : 5 bits
-   * current_next_indicator : 1 bit */
-  tmp = *data++;
-  section->version_number = (tmp >> 1) & 0x1F;
-  section->current_next_indicator = tmp & 0x01;
+  MpegTSPacketizer2 *packetizer;
 
-  /* skip already handled section_number and last_section_number */
-  data += 2;
+  packetizer =
+      GST_MPEGTS_PACKETIZER (g_object_new (GST_TYPE_MPEGTS_PACKETIZER, NULL));
 
-  cat_info = gst_structure_new_id_empty (QUARK_CAT);
-
-  /* descriptors */
-  desc_len = section->section_length - 4 - 8;
-  gst_mpeg_descriptor_parse (&desc, data, desc_len);
-  descriptors =
-      mpegts_packetizer_parse_descriptors (packetizer, &data, data + desc_len);
-  if (descriptors == NULL)
-    goto error;
-  set_descriptors_array_on_structure (cat_info, QUARK_DESCRIPTORS, descriptors);
-
-  return cat_info;
-error:
-  if (cat_info)
-    gst_structure_free (cat_info);
-  return NULL;
+  return packetizer;
 }
 
-GstStructure *
-mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
+void
+mpegts_packetizer_push (MpegTSPacketizer2 * packetizer, GstBuffer * buffer)
 {
-  GstStructure *pat_info = NULL;
-  guint8 *data, *end;
-  guint transport_stream_id;
-  guint8 tmp;
-  guint program_number;
-  guint pmt_pid;
-  GValue entries = { 0 };
-  GValue value = { 0 };
-  GstStructure *entry = NULL;
-  gchar *struct_name;
-
-  data = section->data;
-
-  data += 3;
+  if (G_UNLIKELY (packetizer->empty)) {
+    packetizer->empty = FALSE;
+    packetizer->offset = GST_BUFFER_OFFSET (buffer);
+  }
 
-  transport_stream_id = GST_READ_UINT16_BE (data);
-  data += 2;
+  GST_DEBUG ("Pushing %" G_GSIZE_FORMAT " byte from offset %"
+      G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
+      GST_BUFFER_OFFSET (buffer));
+  gst_adapter_push (packetizer->adapter, buffer);
+  packetizer->priv->available += gst_buffer_get_size (buffer);
+  /* If buffer timestamp is valid, store it */
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)))
+    packetizer->priv->last_in_time = GST_BUFFER_TIMESTAMP (buffer);
+}
 
-  tmp = *data++;
-  section->version_number = (tmp >> 1) & 0x1F;
-  section->current_next_indicator = tmp & 0x01;
+static gboolean
+mpegts_try_discover_packet_size (MpegTSPacketizer2 * packetizer)
+{
+  guint8 *dest;
+  int i, pos = -1, j;
+  static const guint psizes[] = {
+    MPEGTS_NORMAL_PACKETSIZE,
+    MPEGTS_M2TS_PACKETSIZE,
+    MPEGTS_DVB_ASI_PACKETSIZE,
+    MPEGTS_ATSC_PACKETSIZE
+  };
 
-  /* skip section_number and last_section_number */
-  data += 2;
 
-  pat_info = gst_structure_new_id (QUARK_PAT,
-      QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, NULL);
-  g_value_init (&entries, GST_TYPE_LIST);
-  /* stop at the CRC */
-  end = section->data + section->section_length;
-  while (data < end - 4) {
-    program_number = GST_READ_UINT16_BE (data);
-    data += 2;
+  dest = g_malloc (MPEGTS_MAX_PACKETSIZE * 4);
+  /* wait for 3 sync bytes */
+  while (packetizer->priv->available >= MPEGTS_MAX_PACKETSIZE * 4) {
 
-    pmt_pid = GST_READ_UINT16_BE (data) & 0x1FFF;
-    data += 2;
+    /* check for sync bytes */
+    gst_adapter_copy (packetizer->adapter, dest, 0, MPEGTS_MAX_PACKETSIZE * 4);
+    /* find first sync byte */
+    pos = -1;
+    for (i = 0; i < MPEGTS_MAX_PACKETSIZE; i++) {
+      if (dest[i] == PACKET_SYNC_BYTE) {
+        for (j = 0; j < 4; j++) {
+          guint packetsize = psizes[j];
+          /* check each of the packet size possibilities in turn */
+          if (dest[i] == PACKET_SYNC_BYTE
+              && dest[i + packetsize] == PACKET_SYNC_BYTE
+              && dest[i + packetsize * 2] == PACKET_SYNC_BYTE
+              && dest[i + packetsize * 3] == PACKET_SYNC_BYTE) {
+            packetizer->know_packet_size = TRUE;
+            packetizer->packet_size = packetsize;
+            packetizer->caps = gst_caps_new_simple ("video/mpegts",
+                "systemstream", G_TYPE_BOOLEAN, TRUE,
+                "packetsize", G_TYPE_INT, packetsize, NULL);
+            if (packetsize == MPEGTS_M2TS_PACKETSIZE)
+              pos = i - 4;
+            else
+              pos = i;
+            break;
+          }
+        }
+        break;
+      }
+    }
 
-    struct_name = g_strdup_printf ("program-%d", program_number);
-    entry = gst_structure_new_empty (struct_name);
-    g_free (struct_name);
-    gst_structure_id_set (entry, QUARK_PROGRAM_NUMBER, G_TYPE_UINT,
-        program_number, QUARK_PID, G_TYPE_UINT, pmt_pid, NULL);
+    if (packetizer->know_packet_size)
+      break;
 
-    g_value_init (&value, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&value, entry);
-    gst_value_list_append_and_take_value (&entries, &value);
+    /* Skip MPEGTS_MAX_PACKETSIZE */
+    gst_adapter_flush (packetizer->adapter, MPEGTS_MAX_PACKETSIZE);
+    packetizer->priv->available -= MPEGTS_MAX_PACKETSIZE;
+    packetizer->offset += MPEGTS_MAX_PACKETSIZE;
   }
 
-  gst_structure_id_take_value (pat_info, QUARK_PROGRAMS, &entries);
-
-  if (data != end - 4) {
-    /* FIXME: check the CRC before parsing the packet */
-    GST_ERROR ("at the end of PAT data != end - 4");
-    gst_structure_free (pat_info);
+  g_free (dest);
 
-    return NULL;
+  if (packetizer->know_packet_size) {
+    GST_DEBUG ("have packetsize detected: %d of %u bytes",
+        packetizer->know_packet_size, packetizer->packet_size);
+    /* flush to sync byte */
+    if (pos > 0) {
+      GST_DEBUG ("Flushing out %d bytes", pos);
+      gst_adapter_flush (packetizer->adapter, pos);
+      packetizer->offset += pos;
+      packetizer->priv->available -= MPEGTS_MAX_PACKETSIZE;
+    }
+  } else {
+    /* drop invalid data and move to the next possible packets */
+    GST_DEBUG ("Could not determine packet size");
   }
 
-  return pat_info;
+  return packetizer->know_packet_size;
 }
 
-GstStructure *
-mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
+gboolean
+mpegts_packetizer_has_packets (MpegTSPacketizer2 * packetizer)
 {
-  GstStructure *pmt = NULL;
-  guint8 *data, *end;
-  guint16 program_number;
-  guint8 tmp;
-  guint pcr_pid;
-  guint program_info_length;
-  guint8 stream_type;
-  guint16 pid;
-  guint stream_info_length;
-  GValueArray *descriptors;
-  GValue stream_value = { 0 };
-  GValue programs = { 0 };
-  GstStructure *stream_info = NULL;
-  gchar *struct_name;
-
-  /* fixed header + CRC == 16 */
-  if (section->section_length < 16) {
-    GST_WARNING ("PID %d invalid PMT size %d",
-        section->pid, section->section_length);
-    goto error;
+  if (G_UNLIKELY (packetizer->know_packet_size == FALSE)) {
+    if (!mpegts_try_discover_packet_size (packetizer))
+      return FALSE;
   }
+  return packetizer->priv->available >= packetizer->packet_size;
+}
 
-  data = section->data;
-  end = data + section->section_length;
-
-  data += 3;
-
-  program_number = GST_READ_UINT16_BE (data);
-  data += 2;
-
-  GST_DEBUG ("Parsing %d Program Map Table", program_number);
-
-  tmp = *data++;
-  section->version_number = (tmp >> 1) & 0x1F;
-  section->current_next_indicator = tmp & 0x01;
-
-  /* skip section_number and last_section_number */
-  data += 2;
-
-  pcr_pid = GST_READ_UINT16_BE (data) & 0x1FFF;
-  data += 2;
+MpegTSPacketizerPacketReturn
+mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer,
+    MpegTSPacketizerPacket * packet)
+{
+  MpegTSPacketizerPrivate *priv = packetizer->priv;
+  guint skip;
+  guint sync_offset;
 
-  program_info_length = GST_READ_UINT16_BE (data) & 0x0FFF;
-  data += 2;
+  if (G_UNLIKELY (!packetizer->know_packet_size)) {
+    if (!mpegts_try_discover_packet_size (packetizer))
+      return PACKET_NEED_MORE;
+  }
 
-  pmt = gst_structure_new_id (QUARK_PMT,
-      QUARK_PROGRAM_NUMBER, G_TYPE_UINT, program_number,
-      QUARK_PCR_PID, G_TYPE_UINT, pcr_pid,
-      QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, NULL);
-
-  if (program_info_length) {
-    /* check that the buffer is large enough to contain at least
-     * program_info_length bytes + CRC */
-    if (data + program_info_length + 4 > end) {
-      GST_WARNING ("PID %d invalid program info length %d left %d",
-          section->pid, program_info_length, (gint) (end - data));
-      goto error;
+  while (priv->available >= packetizer->packet_size) {
+    if (priv->mapped == NULL) {
+      priv->mapped_size = priv->available;
+      priv->mapped =
+          (guint8 *) gst_adapter_map (packetizer->adapter, priv->mapped_size);
+      priv->offset = 0;
     }
 
-    descriptors =
-        mpegts_packetizer_parse_descriptors (packetizer, &data,
-        data + program_info_length);
-    if (descriptors == NULL)
-      goto error;
-
-    set_descriptors_array_on_structure (pmt, QUARK_DESCRIPTORS, descriptors);
-  }
-
-  g_value_init (&programs, GST_TYPE_LIST);
-  /* parse entries, cycle until there's space for another entry (at least 5
-   * bytes) plus the CRC */
-  while (data <= end - 4 - 5) {
-    stream_type = *data++;
-    GST_DEBUG ("Stream type 0x%02x found", stream_type);
-
-    pid = GST_READ_UINT16_BE (data) & 0x1FFF;
-    data += 2;
-
-    stream_info_length = GST_READ_UINT16_BE (data) & 0x0FFF;
-    data += 2;
-
-    if (data + stream_info_length + 4 > end) {
-      GST_WARNING ("PID %d invalid stream info length %d left %d", section->pid,
-          stream_info_length, (gint) (end - data));
-      g_value_unset (&programs);
-      goto error;
-    }
-
-    struct_name = g_strdup_printf ("pid-%d", pid);
-    stream_info = gst_structure_new_empty (struct_name);
-    g_free (struct_name);
-    gst_structure_id_set (stream_info,
-        QUARK_PID, G_TYPE_UINT, pid, QUARK_STREAM_TYPE, G_TYPE_UINT,
-        stream_type, NULL);
-
-    if (stream_info_length) {
-      /* check for AC3 descriptor */
-      GstMPEGDescriptor desc;
-
-      if (gst_mpeg_descriptor_parse (&desc, data, stream_info_length)) {
-        /* DVB AC3 */
-        guint8 *desc_data;
-        if (gst_mpeg_descriptor_find (&desc, DESC_DVB_AC3)) {
-          gst_structure_set (stream_info, "has-ac3", G_TYPE_BOOLEAN, TRUE,
-              NULL);
-        }
-
-        /* DATA BROADCAST ID */
-        desc_data =
-            gst_mpeg_descriptor_find (&desc, DESC_DVB_DATA_BROADCAST_ID);
-        if (desc_data) {
-          guint16 data_broadcast_id;
-          data_broadcast_id =
-              DESC_DVB_DATA_BROADCAST_ID_data_broadcast_id (desc_data);
-          gst_structure_set (stream_info, "data-broadcast-id", G_TYPE_UINT,
-              data_broadcast_id, NULL);
-        }
-
-        /* DATA BROADCAST */
-        desc_data = gst_mpeg_descriptor_find (&desc, DESC_DVB_DATA_BROADCAST);
-        if (desc_data) {
-          GstStructure *databroadcast_info;
-          guint16 data_broadcast_id;
-          guint8 component_tag;
-          data_broadcast_id =
-              DESC_DVB_DATA_BROADCAST_data_broadcast_id (desc_data);
-          component_tag = DESC_DVB_DATA_BROADCAST_component_tag (desc_data);
-          databroadcast_info = gst_structure_new ("data-broadcast", "id",
-              G_TYPE_UINT, data_broadcast_id, "component-tag", component_tag,
-              NULL);
-          gst_structure_set (stream_info, "data-broadcast", GST_TYPE_STRUCTURE,
-              databroadcast_info, NULL);
-        }
-
-        /* DVB CAROUSEL IDENTIFIER */
-        desc_data =
-            gst_mpeg_descriptor_find (&desc, DESC_DVB_CAROUSEL_IDENTIFIER);
-        if (desc_data) {
-          guint32 carousel_id;
-          carousel_id = DESC_DVB_CAROUSEL_IDENTIFIER_carousel_id (desc_data);
-          gst_structure_set (stream_info, "carousel-id", G_TYPE_UINT,
-              carousel_id, NULL);
-        }
-
-        /* DVB STREAM IDENTIFIER */
-        desc_data =
-            gst_mpeg_descriptor_find (&desc, DESC_DVB_STREAM_IDENTIFIER);
-        if (desc_data) {
-          guint8 component_tag;
-          component_tag = DESC_DVB_STREAM_IDENTIFIER_component_tag (desc_data);
-          gst_structure_set (stream_info, "component-tag", G_TYPE_UINT,
-              component_tag, NULL);
-        }
-
-        /* ISO 639 LANGUAGE */
-        desc_data = gst_mpeg_descriptor_find (&desc, DESC_ISO_639_LANGUAGE);
-        if (!desc_data) {
-          desc_data = gst_mpeg_descriptor_find (&desc, DESC_DVB_SUBTITLING);
-        }
-        if (desc_data && DESC_ISO_639_LANGUAGE_codes_n (desc_data)) {
-          gchar *lang_code;
-          gchar *language_n = (gchar *)
-              DESC_ISO_639_LANGUAGE_language_code_nth (desc_data, 0);
-          lang_code = g_strndup (language_n, 3);
-          gst_structure_set (stream_info, "lang-code", G_TYPE_STRING,
-              lang_code, NULL);
-          g_free (lang_code);
-        }
-
-        descriptors =
-            mpegts_packetizer_parse_descriptors (packetizer, &data,
-            data + stream_info_length);
-        if (descriptors == NULL) {
-          g_value_unset (&programs);
-          gst_structure_free (stream_info);
-          goto error;
-        }
-
-        set_descriptors_array_on_structure (stream_info, QUARK_DESCRIPTORS,
-            descriptors);
-      }
-    }
-
-    g_value_init (&stream_value, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&stream_value, stream_info);
-    gst_value_list_append_and_take_value (&programs, &stream_value);
-  }
-
-  gst_structure_id_take_value (pmt, QUARK_STREAMS, &programs);
-
-  g_assert (data == end - 4);
-
-  return pmt;
-
-error:
-  if (pmt)
-    gst_structure_free (pmt);
-
-  return NULL;
-}
-
-GstStructure *
-mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
-{
-  GstStructure *nit = NULL, *transport = NULL, *delivery_structure = NULL;
-  guint8 *data, *end, *entry_begin;
-  guint16 network_id, transport_stream_id, original_network_id;
-  guint tmp;
-  guint16 descriptors_loop_length, transport_stream_loop_length;
-  GValue transports = { 0 };
-  GValue transport_value = { 0 };
-  GValue tmpval = G_VALUE_INIT;
-  GValueArray *descriptors = NULL;
-
-  GST_DEBUG ("NIT");
-
-  /* fixed header + CRC == 16 */
-  if (section->section_length < 23) {
-    GST_WARNING ("PID %d invalid NIT size %d",
-        section->pid, section->section_length);
-    goto error;
-  }
-
-  data = section->data;
-  end = data + section->section_length;
-
-  data += 3;
-
-  network_id = GST_READ_UINT16_BE (data);
-  data += 2;
-
-  tmp = *data++;
-  section->version_number = (tmp >> 1) & 0x1F;
-  section->current_next_indicator = tmp & 0x01;
-
-  /* skip section_number and last_section_number */
-  data += 2;
-
-  descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
-  data += 2;
-
-  nit = gst_structure_new_id (QUARK_NIT,
-      QUARK_NETWORK_ID, G_TYPE_UINT, network_id,
-      QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number,
-      QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT,
-      section->current_next_indicator, QUARK_ACTUAL_NETWORK, G_TYPE_BOOLEAN,
-      section->table_id == 0x40, NULL);
-
-  /* see if the buffer is large enough */
-  if (descriptors_loop_length) {
-    guint8 *networkname_descriptor;
-    GstMPEGDescriptor mpegdescriptor;
-
-    if (data + descriptors_loop_length > end - 4) {
-      GST_WARNING ("PID %d invalid NIT descriptors loop length %d",
-          section->pid, descriptors_loop_length);
-      gst_structure_free (nit);
-      goto error;
-    }
-    if (gst_mpeg_descriptor_parse (&mpegdescriptor, data,
-            descriptors_loop_length)) {
-      networkname_descriptor =
-          gst_mpeg_descriptor_find (&mpegdescriptor, DESC_DVB_NETWORK_NAME);
-      if (networkname_descriptor != NULL) {
-        gchar *networkname_tmp;
-
-        /* No need to bounds check this value as it comes from the descriptor length itself */
-        guint8 networkname_length =
-            DESC_DVB_NETWORK_NAME_length (networkname_descriptor);
-        gchar *networkname =
-            (gchar *) DESC_DVB_NETWORK_NAME_text (networkname_descriptor);
-
-        networkname_tmp =
-            get_encoding_and_convert (packetizer, networkname,
-            networkname_length);
-        gst_structure_id_set (nit, QUARK_NETWORK_NAME, G_TYPE_STRING,
-            networkname_tmp, NULL);
-        g_free (networkname_tmp);
-      }
-
-      descriptors =
-          mpegts_packetizer_parse_descriptors (packetizer, &data,
-          data + descriptors_loop_length);
-      if (!descriptors) {
-        gst_structure_free (nit);
-        goto error;
-      }
-      set_descriptors_array_on_structure (nit, QUARK_DESCRIPTORS, descriptors);
-    }
-  }
-
-  transport_stream_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
-  data += 2;
-
-  g_value_init (&transports, GST_TYPE_LIST);
-  /* read up to the CRC */
-  while (transport_stream_loop_length - 4 > 0) {
-    gchar *transport_name;
-
-    entry_begin = data;
-
-    if (transport_stream_loop_length < 10) {
-      /* each entry must be at least 6 bytes (+ 4bytes CRC) */
-      GST_WARNING ("PID %d invalid NIT entry size %d",
-          section->pid, transport_stream_loop_length);
-      goto error;
-    }
-
-    transport_stream_id = GST_READ_UINT16_BE (data);
-    data += 2;
-
-    original_network_id = GST_READ_UINT16_BE (data);
-    data += 2;
-
-    descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
-    data += 2;
-
-    transport_name = g_strdup_printf ("transport-%d", transport_stream_id);
-    transport = gst_structure_new_empty (transport_name);
-    g_free (transport_name);
-    gst_structure_id_set (transport,
-        QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id,
-        QUARK_ORIGINAL_NETWORK_ID, G_TYPE_UINT, original_network_id, NULL);
-
-    if (descriptors_loop_length) {
-      GstMPEGDescriptor mpegdescriptor;
-      guint8 *delivery;
-
-      if (data + descriptors_loop_length > end - 4) {
-        GST_WARNING ("PID %d invalid NIT entry %d descriptors loop length %d",
-            section->pid, transport_stream_id, descriptors_loop_length);
-        gst_structure_free (transport);
-        goto error;
-      }
-      gst_mpeg_descriptor_parse (&mpegdescriptor, data,
-          descriptors_loop_length);
-
-      if ((delivery = gst_mpeg_descriptor_find (&mpegdescriptor,
-                  DESC_DVB_SATELLITE_DELIVERY_SYSTEM))) {
-
-        guint8 *frequency_bcd =
-            DESC_DVB_SATELLITE_DELIVERY_SYSTEM_frequency (delivery);
-        guint32 frequency =
-            10 * ((frequency_bcd[3] & 0x0F) +
-            10 * ((frequency_bcd[3] & 0xF0) >> 4) +
-            100 * (frequency_bcd[2] & 0x0F) +
-            1000 * ((frequency_bcd[2] & 0xF0) >> 4) +
-            10000 * (frequency_bcd[1] & 0x0F) +
-            100000 * ((frequency_bcd[1] & 0xF0) >> 4) +
-            1000000 * (frequency_bcd[0] & 0x0F) +
-            10000000 * ((frequency_bcd[0] & 0xF0) >> 4));
-        guint8 *orbital_bcd =
-            DESC_DVB_SATELLITE_DELIVERY_SYSTEM_orbital_position (delivery);
-        gfloat orbital =
-            (orbital_bcd[1] & 0x0F) / 10. + ((orbital_bcd[1] & 0xF0) >> 4) +
-            10 * (orbital_bcd[0] & 0x0F) + 100 * ((orbital_bcd[0] & 0xF0) >> 4);
-        gboolean east =
-            DESC_DVB_SATELLITE_DELIVERY_SYSTEM_west_east_flag (delivery);
-        guint8 polarization =
-            DESC_DVB_SATELLITE_DELIVERY_SYSTEM_polarization (delivery);
-        const gchar *polarization_str;
-        guint8 modulation =
-            DESC_DVB_SATELLITE_DELIVERY_SYSTEM_modulation (delivery);
-        const gchar *modulation_str;
-        guint8 *symbol_rate_bcd =
-            DESC_DVB_SATELLITE_DELIVERY_SYSTEM_symbol_rate (delivery);
-        guint32 symbol_rate =
-            (symbol_rate_bcd[2] & 0x0F) +
-            10 * ((symbol_rate_bcd[2] & 0xF0) >> 4) +
-            100 * (symbol_rate_bcd[1] & 0x0F) +
-            1000 * ((symbol_rate_bcd[1] & 0xF0) >> 4) +
-            10000 * (symbol_rate_bcd[0] & 0x0F) +
-            100000 * ((symbol_rate_bcd[0] & 0xF0) >> 4);
-        guint8 fec_inner =
-            DESC_DVB_SATELLITE_DELIVERY_SYSTEM_fec_inner (delivery);
-        const gchar *fec_inner_str;
-
-        switch (polarization) {
-          case 0:
-            polarization_str = "horizontal";
-            break;
-          case 1:
-            polarization_str = "vertical";
-            break;
-          case 2:
-            polarization_str = "left";
-            break;
-          case 3:
-            polarization_str = "right";
-            break;
-          default:
-            polarization_str = "";
-        }
-        switch (fec_inner) {
-          case 0:
-            fec_inner_str = "undefined";
-            break;
-          case 1:
-            fec_inner_str = "1/2";
-            break;
-          case 2:
-            fec_inner_str = "2/3";
-            break;
-          case 3:
-            fec_inner_str = "3/4";
-            break;
-          case 4:
-            fec_inner_str = "5/6";
-            break;
-          case 5:
-            fec_inner_str = "7/8";
-            break;
-          case 6:
-            fec_inner_str = "8/9";
-            break;
-          case 0xF:
-            fec_inner_str = "none";
-            break;
-          default:
-            fec_inner_str = "reserved";
-        }
-        switch (modulation) {
-          case 0x00:
-            modulation_str = "auto";
-            break;
-          case 0x01:
-            modulation_str = "QPSK";
-            break;
-          case 0x02:
-            modulation_str = "8PSK";
-            break;
-          case 0x03:
-            modulation_str = "QAM16";
-            break;
-          default:
-            modulation_str = "";
-            break;
-        }
-        delivery_structure = gst_structure_new ("satellite",
-            "orbital", G_TYPE_FLOAT, orbital,
-            "east-or-west", G_TYPE_STRING, east ? "east" : "west",
-            "modulation", G_TYPE_STRING, modulation_str,
-            "frequency", G_TYPE_UINT, frequency,
-            "polarization", G_TYPE_STRING, polarization_str,
-            "symbol-rate", G_TYPE_UINT, symbol_rate,
-            "inner-fec", G_TYPE_STRING, fec_inner_str, NULL);
-        g_value_init (&tmpval, GST_TYPE_STRUCTURE);
-        g_value_take_boxed (&tmpval, delivery_structure);
-        gst_structure_id_take_value (transport, QUARK_DELIVERY, &tmpval);
-      } else if ((delivery = gst_mpeg_descriptor_find (&mpegdescriptor,
-                  DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM))) {
-
-        guint32 frequency =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_frequency (delivery) * 10;
-        guint8 bandwidth =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_bandwidth (delivery);
-        guint8 constellation =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_constellation (delivery);
-        guint8 hierarchy =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_hierarchy (delivery);
-        guint8 code_rate_hp =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_code_rate_hp (delivery);
-        guint8 code_rate_lp =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_code_rate_lp (delivery);
-        guint8 guard_interval =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_guard_interval (delivery);
-        guint8 transmission_mode =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_transmission_mode (delivery);
-        gboolean other_frequency =
-            DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_other_frequency (delivery);
-        const gchar *constellation_str, *code_rate_hp_str, *code_rate_lp_str,
-            *transmission_mode_str;
-        /* do the stuff */
-        /* bandwidth is 8 if 0, 7 if 1, 6 if 2, reserved otherwise */
-        if (bandwidth <= 2)
-          bandwidth = 8 - bandwidth;
-        else
-          bandwidth = 0;
-        switch (constellation) {
-          case 0:
-            constellation_str = "QPSK";
-            break;
-          case 1:
-            constellation_str = "QAM16";
-            break;
-          case 2:
-            constellation_str = "QAM64";
-            break;
-          default:
-            constellation_str = "reserved";
-        }
-        /* hierarchy is 4 if 3, 2 if 2, 1 if 1, 0 if 0, reserved if > 3 */
-        if (hierarchy <= 3) {
-          if (hierarchy == 3)
-            hierarchy = 4;
-        } else {
-          hierarchy = 0;
-        }
-
-        switch (code_rate_hp) {
-          case 0:
-            code_rate_hp_str = "1/2";
-            break;
-          case 1:
-            code_rate_hp_str = "2/3";
-            break;
-          case 2:
-            code_rate_hp_str = "3/4";
-            break;
-          case 3:
-            code_rate_hp_str = "5/6";
-            break;
-          case 4:
-            code_rate_hp_str = "7/8";
-            break;
-          default:
-            code_rate_hp_str = "reserved";
-        }
-
-        switch (code_rate_lp) {
-          case 0:
-            code_rate_lp_str = "1/2";
-            break;
-          case 1:
-            code_rate_lp_str = "2/3";
-            break;
-          case 2:
-            code_rate_lp_str = "3/4";
-            break;
-          case 3:
-            code_rate_lp_str = "5/6";
-            break;
-          case 4:
-            code_rate_lp_str = "7/8";
-            break;
-          default:
-            code_rate_lp_str = "reserved";
-        }
-        /* guard is 32 if 0, 16 if 1, 8 if 2, 4 if 3 */
-        switch (guard_interval) {
-          case 0:
-            guard_interval = 32;
-            break;
-          case 1:
-            guard_interval = 16;
-            break;
-          case 2:
-            guard_interval = 8;
-            break;
-          case 3:
-            guard_interval = 4;
-            break;
-          default:             /* make it default to 32 */
-            guard_interval = 32;
-        }
-        switch (transmission_mode) {
-          case 0:
-            transmission_mode_str = "2k";
-            break;
-          case 1:
-            transmission_mode_str = "8k";
-            break;
-          default:
-            transmission_mode_str = "reserved";
-        }
-        delivery_structure = gst_structure_new_id (QUARK_TERRESTRIAL,
-            QUARK_FREQUENCY, G_TYPE_UINT, frequency,
-            QUARK_BANDWIDTH, G_TYPE_UINT, bandwidth,
-            QUARK_CONSTELLATION, G_TYPE_STRING, constellation_str,
-            QUARK_HIERARCHY, G_TYPE_UINT, hierarchy,
-            QUARK_CODE_RATE_HP, G_TYPE_STRING, code_rate_hp_str,
-            QUARK_CODE_RATE_LP, G_TYPE_STRING, code_rate_lp_str,
-            QUARK_GUARD_INTERVAL, G_TYPE_UINT, guard_interval,
-            QUARK_TRANSMISSION_MODE, G_TYPE_STRING, transmission_mode_str,
-            QUARK_OTHER_FREQUENCY, G_TYPE_BOOLEAN, other_frequency, NULL);
-        g_value_init (&tmpval, GST_TYPE_STRUCTURE);
-        g_value_take_boxed (&tmpval, delivery_structure);
-        gst_structure_id_take_value (transport, QUARK_DELIVERY, &tmpval);
-      } else if ((delivery = gst_mpeg_descriptor_find (&mpegdescriptor,
-                  DESC_DVB_CABLE_DELIVERY_SYSTEM))) {
-
-        guint8 *frequency_bcd =
-            DESC_DVB_CABLE_DELIVERY_SYSTEM_frequency (delivery);
-        /* see en 300 468 section 6.2.13.1 least significant bcd digit
-         * is measured in 100Hz units so multiplier needs to be 100 to get
-         * into Hz */
-        guint32 frequency = 100 *
-            ((frequency_bcd[3] & 0x0F) +
-            10 * ((frequency_bcd[3] & 0xF0) >> 4) +
-            100 * (frequency_bcd[2] & 0x0F) +
-            1000 * ((frequency_bcd[2] & 0xF0) >> 4) +
-            10000 * (frequency_bcd[1] & 0x0F) +
-            100000 * ((frequency_bcd[1] & 0xF0) >> 4) +
-            1000000 * (frequency_bcd[0] & 0x0F) +
-            10000000 * ((frequency_bcd[0] & 0xF0) >> 4));
-        guint8 modulation =
-            DESC_DVB_CABLE_DELIVERY_SYSTEM_modulation (delivery);
-        const gchar *modulation_str;
-        guint8 *symbol_rate_bcd =
-            DESC_DVB_CABLE_DELIVERY_SYSTEM_symbol_rate (delivery);
-        guint32 symbol_rate =
-            (symbol_rate_bcd[2] & 0x0F) +
-            10 * ((symbol_rate_bcd[2] & 0xF0) >> 4) +
-            100 * (symbol_rate_bcd[1] & 0x0F) +
-            1000 * ((symbol_rate_bcd[1] & 0xF0) >> 4) +
-            10000 * (symbol_rate_bcd[0] & 0x0F) +
-            100000 * ((symbol_rate_bcd[0] & 0xF0) >> 4);
-        guint8 fec_inner = DESC_DVB_CABLE_DELIVERY_SYSTEM_fec_inner (delivery);
-        const gchar *fec_inner_str;
-
-        switch (fec_inner) {
-          case 0:
-            fec_inner_str = "undefined";
-            break;
-          case 1:
-            fec_inner_str = "1/2";
-            break;
-          case 2:
-            fec_inner_str = "2/3";
-            break;
-          case 3:
-            fec_inner_str = "3/4";
-            break;
-          case 4:
-            fec_inner_str = "5/6";
-            break;
-          case 5:
-            fec_inner_str = "7/8";
-            break;
-          case 6:
-            fec_inner_str = "8/9";
-            break;
-          case 0xF:
-            fec_inner_str = "none";
-            break;
-          default:
-            fec_inner_str = "reserved";
-        }
-        switch (modulation) {
-          case 0x00:
-            modulation_str = "undefined";
-            break;
-          case 0x01:
-            modulation_str = "QAM16";
-            break;
-          case 0x02:
-            modulation_str = "QAM32";
-            break;
-          case 0x03:
-            modulation_str = "QAM64";
-            break;
-          case 0x04:
-            modulation_str = "QAM128";
-            break;
-          case 0x05:
-            modulation_str = "QAM256";
-            break;
-          default:
-            modulation_str = "reserved";
-        }
-        delivery_structure = gst_structure_new_id (QUARK_CABLE,
-            QUARK_MODULATION, G_TYPE_STRING, modulation_str,
-            QUARK_FREQUENCY, G_TYPE_UINT, frequency,
-            QUARK_SYMBOL_RATE, G_TYPE_UINT, symbol_rate,
-            QUARK_INNER_FEC, G_TYPE_STRING, fec_inner_str, NULL);
-        g_value_init (&tmpval, GST_TYPE_STRUCTURE);
-        g_value_take_boxed (&tmpval, delivery_structure);
-        gst_structure_id_take_value (transport, QUARK_DELIVERY, &tmpval);
-      }
-      if ((delivery = gst_mpeg_descriptor_find (&mpegdescriptor,
-                  DESC_DTG_LOGICAL_CHANNEL))) {
-        guint8 *current_pos = delivery + 2;
-        GValue channel_numbers = { 0 };
-
-        g_value_init (&channel_numbers, GST_TYPE_LIST);
-        while (current_pos < delivery + DESC_LENGTH (delivery)) {
-          GstStructure *channel;
-          GValue channel_value = { 0 };
-          guint16 service_id = GST_READ_UINT16_BE (current_pos);
-          guint16 logical_channel_number;
-
-          current_pos += 2;
-          logical_channel_number = GST_READ_UINT16_BE (current_pos) & 0x03ff;
-          channel = gst_structure_new_id (QUARK_CHANNELS,
-              QUARK_SERVICE_ID, G_TYPE_UINT,
-              service_id, QUARK_LOGICAL_CHANNEL_NUMBER, G_TYPE_UINT,
-              logical_channel_number, NULL);
-          g_value_init (&channel_value, GST_TYPE_STRUCTURE);
-          g_value_take_boxed (&channel_value, channel);
-          gst_value_list_append_and_take_value (&channel_numbers,
-              &channel_value);
-          current_pos += 2;
-        }
-        gst_structure_id_take_value (transport, QUARK_CHANNELS,
-            &channel_numbers);
-      }
-      if ((delivery = gst_mpeg_descriptor_find (&mpegdescriptor,
-                  DESC_DVB_FREQUENCY_LIST))) {
-        guint8 *current_pos = delivery + 2;
-        GValue frequencies = { 0 };
-        guint8 type;
-
-        type = *current_pos & 0x03;
-        current_pos++;
-
-        if (type) {
-          const gchar *fieldname = NULL;
-          g_value_init (&frequencies, GST_TYPE_LIST);
-
-          while (current_pos < delivery + DESC_LENGTH (delivery) - 3) {
-            guint32 freq = 0;
-            guint8 *frequency_bcd = current_pos;
-            GValue frequency = { 0 };
-
-            switch (type) {
-              case 0x01:
-                /* satellite */
-                freq =
-                    10 * ((frequency_bcd[3] & 0x0F) +
-                    10 * ((frequency_bcd[3] & 0xF0) >> 4) +
-                    100 * (frequency_bcd[2] & 0x0F) +
-                    1000 * ((frequency_bcd[2] & 0xF0) >> 4) +
-                    10000 * (frequency_bcd[1] & 0x0F) +
-                    100000 * ((frequency_bcd[1] & 0xF0) >> 4) +
-                    1000000 * (frequency_bcd[0] & 0x0F) +
-                    10000000 * ((frequency_bcd[0] & 0xF0) >> 4));
-                break;
-              case 0x02:
-                /* cable */
-                freq = 100 *
-                    ((frequency_bcd[3] & 0x0F) +
-                    10 * ((frequency_bcd[3] & 0xF0) >> 4) +
-                    100 * (frequency_bcd[2] & 0x0F) +
-                    1000 * ((frequency_bcd[2] & 0xF0) >> 4) +
-                    10000 * (frequency_bcd[1] & 0x0F) +
-                    100000 * ((frequency_bcd[1] & 0xF0) >> 4) +
-                    1000000 * (frequency_bcd[0] & 0x0F) +
-                    10000000 * ((frequency_bcd[0] & 0xF0) >> 4));
-                break;
-              case 0x03:
-                /* terrestrial */
-                freq = GST_READ_UINT32_BE (current_pos) * 10;
-                break;
-            }
-            g_value_init (&frequency, G_TYPE_UINT);
-            g_value_set_uint (&frequency, freq);
-            gst_value_list_append_and_take_value (&frequencies, &frequency);
-            current_pos += 4;
-          }
-
-          switch (type) {
-            case 0x01:
-              fieldname = "frequency-list-satellite";
-              break;
-            case 0x02:
-              fieldname = "frequency-list-cable";
-              break;
-            case 0x03:
-              fieldname = "frequency-list-terrestrial";
-              break;
-          }
-
-          gst_structure_take_value (transport, fieldname, &frequencies);
-        }
-      }
-
-      descriptors =
-          mpegts_packetizer_parse_descriptors (packetizer, &data,
-          data + descriptors_loop_length);
-      if (!descriptors) {
-        gst_structure_free (transport);
-        goto error;
-      }
-
-      set_descriptors_array_on_structure (transport, QUARK_DESCRIPTORS,
-          descriptors);
-    }
-
-    g_value_init (&transport_value, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&transport_value, transport);
-    gst_value_list_append_and_take_value (&transports, &transport_value);
-
-    transport_stream_loop_length -= data - entry_begin;
-  }
-
-  if (data != end - 4) {
-    GST_WARNING ("PID %d invalid NIT parsed %d length %d",
-        section->pid, (gint) (data - section->data), section->section_length);
-    goto error;
-  }
-
-  gst_structure_id_take_value (nit, QUARK_TRANSPORTS, &transports);
-
-  GST_DEBUG ("NIT %" GST_PTR_FORMAT, nit);
-
-  return nit;
-
-error:
-  if (nit)
-    gst_structure_free (nit);
-
-  if (GST_VALUE_HOLDS_LIST (&transports))
-    g_value_unset (&transports);
-
-  return NULL;
-}
-
-GstStructure *
-mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
-{
-  GstStructure *sdt = NULL, *service = NULL;
-  guint8 *data, *end, *entry_begin;
-  guint16 transport_stream_id, original_network_id, service_id;
-  guint tmp;
-  guint sdt_info_length;
-  guint8 running_status;
-  gboolean scrambled;
-  guint descriptors_loop_length;
-  GValue services = { 0 };
-  GValueArray *descriptors = NULL;
-  GValue service_value = { 0 };
-
-  GST_DEBUG ("SDT");
-
-  /* fixed header + CRC == 16 */
-  if (section->section_length < 14) {
-    GST_WARNING ("PID %d invalid SDT size %d",
-        section->pid, section->section_length);
-    goto error;
-  }
-
-  data = section->data;
-  end = data + section->section_length;
-
-  data += 3;
-
-  transport_stream_id = GST_READ_UINT16_BE (data);
-  data += 2;
-
-  tmp = *data++;
-  section->version_number = (tmp >> 1) & 0x1F;
-  section->current_next_indicator = tmp & 0x01;
-
-  /* skip section_number and last_section_number */
-  data += 2;
-
-  original_network_id = GST_READ_UINT16_BE (data);
-  data += 2;
-
-  /* skip reserved byte */
-  data += 1;
-
-  sdt = gst_structure_new_id (QUARK_SDT,
-      QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id,
-      QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number,
-      QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT,
-      section->current_next_indicator, QUARK_ORIGINAL_NETWORK_ID, G_TYPE_UINT,
-      original_network_id, QUARK_ACTUAL_TRANSPORT_STREAM, G_TYPE_BOOLEAN,
-      section->table_id == 0x42, NULL);
-
-  sdt_info_length = section->section_length - 11;
-  g_value_init (&services, GST_TYPE_LIST);
-  /* read up to the CRC */
-  while (sdt_info_length - 4 > 0) {
-    gchar *service_name;
-
-    entry_begin = data;
-
-    if (sdt_info_length < 9) {
-      /* each entry must be at least 5 bytes (+4 bytes for the CRC) */
-      GST_WARNING ("PID %d invalid SDT entry size %d",
-          section->pid, sdt_info_length);
-      goto error;
-    }
-
-    service_id = GST_READ_UINT16_BE (data);
-    data += 2;
-
-    /* EIT_schedule = ((*data & 0x02) == 2); */
-    /* EIT_present_following = (*data & 0x01) == 1; */
-
-    data += 1;
-    tmp = GST_READ_UINT16_BE (data);
-
-    running_status = (*data >> 5) & 0x07;
-    scrambled = (*data >> 4) & 0x01;
-    descriptors_loop_length = tmp & 0x0FFF;
-    data += 2;
-
-    /* TODO send tag event down relevant pad for channel name and provider */
-    service_name = g_strdup_printf ("service-%d", service_id);
-    service = gst_structure_new_empty (service_name);
-    g_free (service_name);
-
-    if (descriptors_loop_length) {
-      guint8 *service_descriptor;
-      GstMPEGDescriptor mpegdescriptor;
-
-      if (data + descriptors_loop_length > end - 4) {
-        GST_WARNING ("PID %d invalid SDT entry %d descriptors loop length %d",
-            section->pid, service_id, descriptors_loop_length);
-        gst_structure_free (service);
-        goto error;
-      }
-      gst_mpeg_descriptor_parse (&mpegdescriptor, data,
-          descriptors_loop_length);
-      service_descriptor =
-          gst_mpeg_descriptor_find (&mpegdescriptor, DESC_DVB_SERVICE);
-      if (service_descriptor != NULL) {
-        gchar *servicename_tmp, *serviceprovider_name_tmp;
-        guint8 serviceprovider_name_length =
-            DESC_DVB_SERVICE_provider_name_length (service_descriptor);
-        gchar *serviceprovider_name =
-            (gchar *) DESC_DVB_SERVICE_provider_name_text (service_descriptor);
-        guint8 servicename_length =
-            DESC_DVB_SERVICE_name_length (service_descriptor);
-        gchar *servicename =
-            (gchar *) DESC_DVB_SERVICE_name_text (service_descriptor);
-        if (servicename_length + serviceprovider_name_length + 2 <=
-            DESC_LENGTH (service_descriptor)) {
-          const gchar *running_status_tmp;
-          switch (running_status) {
-            case 0:
-              running_status_tmp = "undefined";
-              break;
-            case 1:
-              running_status_tmp = "not running";
-              break;
-            case 2:
-              running_status_tmp = "starts in a few seconds";
-              break;
-            case 3:
-              running_status_tmp = "pausing";
-              break;
-            case 4:
-              running_status_tmp = "running";
-              break;
-            default:
-              running_status_tmp = "reserved";
-          }
-          servicename_tmp =
-              get_encoding_and_convert (packetizer, servicename,
-              servicename_length);
-          serviceprovider_name_tmp =
-              get_encoding_and_convert (packetizer, serviceprovider_name,
-              serviceprovider_name_length);
-
-          gst_structure_set (service,
-              "name", G_TYPE_STRING, servicename_tmp,
-              "provider-name", G_TYPE_STRING, serviceprovider_name_tmp,
-              "scrambled", G_TYPE_BOOLEAN, scrambled,
-              "running-status", G_TYPE_STRING, running_status_tmp, NULL);
-
-          g_free (servicename_tmp);
-          g_free (serviceprovider_name_tmp);
-        }
-      }
-
-      descriptors = mpegts_packetizer_parse_descriptors (packetizer,
-          &data, data + descriptors_loop_length);
-      if (!descriptors) {
-        gst_structure_free (service);
-        goto error;
-      }
-      set_descriptors_array_on_structure (service, QUARK_DESCRIPTORS,
-          descriptors);
-    }
-
-    g_value_init (&service_value, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&service_value, service);
-    gst_value_list_append_and_take_value (&services, &service_value);
-
-    sdt_info_length -= data - entry_begin;
-  }
-
-  if (data != end - 4) {
-    GST_WARNING ("PID %d invalid SDT parsed %d length %d",
-        section->pid, (gint) (data - section->data), section->section_length);
-    goto error;
-  }
-
-  gst_structure_id_take_value (sdt, QUARK_SERVICES, &services);
-
-  return sdt;
-
-error:
-  if (sdt)
-    gst_structure_free (sdt);
-
-  if (GST_VALUE_HOLDS_LIST (&services))
-    g_value_unset (&services);
-
-  return NULL;
-}
-
-/* FIXME : Can take up to 50% of total mpeg-ts demuxing cpu usage */
-GstStructure *
-mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
-{
-  GstStructure *eit = NULL, *event = NULL;
-  guint service_id, last_table_id, segment_last_section_number;
-  guint transport_stream_id, original_network_id;
-  gboolean free_ca_mode;
-  guint event_id, running_status;
-  guint16 mjd;
-  guint year, month, day, hour, minute, second;
-  guint duration;
-  guint8 *data, *end, *duration_ptr, *utc_ptr;
-  guint16 descriptors_loop_length;
-  GValue events = { 0 };
-  GValue event_value = { 0 };
-  GValueArray *descriptors = NULL;
-  gchar *event_name;
-  guint tmp;
-
-  /* fixed header + CRC == 16 */
-  if (section->section_length < 18) {
-    GST_WARNING ("PID %d invalid EIT size %d",
-        section->pid, section->section_length);
-    goto error;
-  }
-
-  data = section->data;
-  end = data + section->section_length;
-
-  data += 3;
-
-  service_id = GST_READ_UINT16_BE (data);
-  data += 2;
-
-  tmp = *data++;
-  section->version_number = (tmp >> 1) & 0x1F;
-  section->current_next_indicator = tmp & 0x01;
-
-  /* skip section_number and last_section_number */
-  data += 2;
-
-  transport_stream_id = GST_READ_UINT16_BE (data);
-  data += 2;
-  original_network_id = GST_READ_UINT16_BE (data);
-  data += 2;
-  segment_last_section_number = *data;
-  data += 1;
-  last_table_id = *data;
-  data += 1;
-
-  eit = gst_structure_new_id (QUARK_EIT,
-      QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number,
-      QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT,
-      section->current_next_indicator, QUARK_SERVICE_ID, G_TYPE_UINT,
-      service_id, QUARK_ACTUAL_TRANSPORT_STREAM, G_TYPE_BOOLEAN,
-      (section->table_id == 0x4E || (section->table_id >= 0x50
-              && section->table_id <= 0x5F)), QUARK_PRESENT_FOLLOWING,
-      G_TYPE_BOOLEAN, (section->table_id == 0x4E
-          || section->table_id == 0x4F), QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT,
-      transport_stream_id, QUARK_ORIGINAL_NETWORK_ID, G_TYPE_UINT,
-      original_network_id, QUARK_SEGMENT_LAST_SECTION_NUMBER, G_TYPE_UINT,
-      segment_last_section_number, QUARK_LAST_TABLE_ID, G_TYPE_UINT,
-      last_table_id, NULL);
-
-  g_value_init (&events, GST_TYPE_LIST);
-  while (data < end - 4) {
-    /* 12 is the minimum entry size + CRC */
-    if (end - data < 12 + 4) {
-      GST_WARNING ("PID %d invalid EIT entry length %d",
-          section->pid, (gint) (end - 4 - data));
-      gst_structure_free (eit);
-      goto error;
-    }
-
-    event_id = GST_READ_UINT16_BE (data);
-    data += 2;
-    /* start_and_duration = GST_READ_UINT64_BE (data); */
-    duration_ptr = data + 5;
-    utc_ptr = data + 2;
-    mjd = GST_READ_UINT16_BE (data);
-    if (mjd == G_MAXUINT16) {
-      year = 1900;
-      month = day = hour = minute = second = 0;
-    } else {
-      /* See EN 300 468 Annex C */
-      year = (guint32) (((mjd - 15078.2) / 365.25));
-      month = (guint8) ((mjd - 14956.1 - (guint) (year * 365.25)) / 30.6001);
-      day = mjd - 14956 - (guint) (year * 365.25) - (guint) (month * 30.6001);
-      if (month == 14 || month == 15) {
-        year++;
-        month = month - 1 - 12;
-      } else {
-        month--;
-      }
-      year += 1900;
-      hour = ((utc_ptr[0] & 0xF0) >> 4) * 10 + (utc_ptr[0] & 0x0F);
-      minute = ((utc_ptr[1] & 0xF0) >> 4) * 10 + (utc_ptr[1] & 0x0F);
-      second = ((utc_ptr[2] & 0xF0) >> 4) * 10 + (utc_ptr[2] & 0x0F);
-    }
-
-    duration = (((duration_ptr[0] & 0xF0) >> 4) * 10 +
-        (duration_ptr[0] & 0x0F)) * 60 * 60 +
-        (((duration_ptr[1] & 0xF0) >> 4) * 10 +
-        (duration_ptr[1] & 0x0F)) * 60 +
-        ((duration_ptr[2] & 0xF0) >> 4) * 10 + (duration_ptr[2] & 0x0F);
-
-    data += 8;
-    running_status = *data >> 5;
-    free_ca_mode = (*data >> 4) & 0x01;
-    descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
-    data += 2;
-
-    /* TODO: send tag event down relevant pad saying what is currently playing */
-    event_name = g_strdup_printf ("event-%d", event_id);
-    event = gst_structure_new_empty (event_name);
-    g_free (event_name);
-    gst_structure_id_set (event,
-        QUARK_EVENT_ID, G_TYPE_UINT, event_id,
-        QUARK_YEAR, G_TYPE_UINT, year,
-        QUARK_MONTH, G_TYPE_UINT, month,
-        QUARK_DAY, G_TYPE_UINT, day,
-        QUARK_HOUR, G_TYPE_UINT, hour,
-        QUARK_MINUTE, G_TYPE_UINT, minute,
-        QUARK_SECOND, G_TYPE_UINT, second,
-        QUARK_DURATION, G_TYPE_UINT, duration,
-        QUARK_RUNNING_STATUS, G_TYPE_UINT, running_status,
-        QUARK_FREE_CA_MODE, G_TYPE_BOOLEAN, free_ca_mode, NULL);
-
-    if (descriptors_loop_length) {
-      guint8 *event_descriptor;
-      GArray *component_descriptors;
-      GArray *extended_event_descriptors;
-      GstMPEGDescriptor mpegdescriptor;
-
-      if (data + descriptors_loop_length > end - 4) {
-        GST_WARNING ("PID %d invalid EIT descriptors loop length %d",
-            section->pid, descriptors_loop_length);
-        gst_structure_free (event);
-        goto error;
-      }
-      gst_mpeg_descriptor_parse (&mpegdescriptor, data,
-          descriptors_loop_length);
-      event_descriptor =
-          gst_mpeg_descriptor_find (&mpegdescriptor, DESC_DVB_SHORT_EVENT);
-      if (event_descriptor != NULL) {
-        gchar *eventname_tmp, *eventdescription_tmp;
-        guint8 eventname_length =
-            DESC_DVB_SHORT_EVENT_name_length (event_descriptor);
-        gchar *eventname =
-            (gchar *) DESC_DVB_SHORT_EVENT_name_text (event_descriptor);
-        guint8 eventdescription_length =
-            DESC_DVB_SHORT_EVENT_description_length (event_descriptor);
-        gchar *eventdescription =
-            (gchar *) DESC_DVB_SHORT_EVENT_description_text (event_descriptor);
-        if (eventname_length + eventdescription_length + 2 <=
-            DESC_LENGTH (event_descriptor)) {
-
-          eventname_tmp =
-              get_encoding_and_convert (packetizer, eventname,
-              eventname_length);
-          eventdescription_tmp =
-              get_encoding_and_convert (packetizer, eventdescription,
-              eventdescription_length);
-
-          gst_structure_id_set (event, QUARK_NAME, G_TYPE_STRING, eventname_tmp,
-              QUARK_DESCRIPTION, G_TYPE_STRING, eventdescription_tmp, NULL);
-          g_free (eventname_tmp);
-          g_free (eventdescription_tmp);
-        }
-      }
-
-      extended_event_descriptors =
-          gst_mpeg_descriptor_find_all (&mpegdescriptor,
-          DESC_DVB_EXTENDED_EVENT);
-      if (extended_event_descriptors) {
-        int i;
-        guint8 *extended_descriptor;
-        GValue extended_items = { 0 };
-        GValue extended_item_value = { 0 };
-        GstStructure *extended_item;
-        gchar *extended_text = NULL;
-        g_value_init (&extended_items, GST_TYPE_LIST);
-        for (i = 0; i < extended_event_descriptors->len; i++) {
-          extended_descriptor = g_array_index (extended_event_descriptors,
-              guint8 *, i);
-          if (DESC_DVB_EXTENDED_EVENT_descriptor_number (extended_descriptor) ==
-              i) {
-            guint8 *items_aux =
-                DESC_DVB_EXTENDED_EVENT_items (extended_descriptor);
-            guint8 *items_limit =
-                items_aux +
-                DESC_DVB_EXTENDED_EVENT_items_length (extended_descriptor);
-            while (items_aux < items_limit) {
-              guint8 length_aux;
-              gchar *description, *text;
-
-              /* Item Description text */
-              length_aux = *items_aux;
-              ++items_aux;
-              description =
-                  get_encoding_and_convert (packetizer, (gchar *) items_aux,
-                  length_aux);
-              items_aux += length_aux;
-
-              /* Item text */
-              length_aux = *items_aux;
-              ++items_aux;
-              text =
-                  get_encoding_and_convert (packetizer, (gchar *) items_aux,
-                  length_aux);
-              items_aux += length_aux;
-
-              extended_item = gst_structure_new_id (QUARK_EXTENDED_ITEM,
-                  QUARK_DESCRIPTION, G_TYPE_STRING, description,
-                  QUARK_TEXT, G_TYPE_STRING, text, NULL);
-              g_free (description);
-              g_free (text);
-
-              g_value_init (&extended_item_value, GST_TYPE_STRUCTURE);
-              g_value_take_boxed (&extended_item_value, extended_item);
-              gst_value_list_append_and_take_value (&extended_items,
-                  &extended_item_value);
-            }
-
-            if (extended_text) {
-              gchar *tmp;
-              gchar *old_extended_text = extended_text;
-              tmp = get_encoding_and_convert (packetizer, (gchar *)
-                  DESC_DVB_EXTENDED_EVENT_text (extended_descriptor),
-                  DESC_DVB_EXTENDED_EVENT_text_length (extended_descriptor));
-              extended_text = g_strdup_printf ("%s%s", extended_text, tmp);
-              g_free (old_extended_text);
-              g_free (tmp);
-            } else {
-              extended_text = get_encoding_and_convert (packetizer, (gchar *)
-                  DESC_DVB_EXTENDED_EVENT_text (extended_descriptor),
-                  DESC_DVB_EXTENDED_EVENT_text_length (extended_descriptor));
-            }
-          }
-        }
-        if (extended_text) {
-          gst_structure_id_set (event, QUARK_EXTENDED_TEXT, G_TYPE_STRING,
-              extended_text, NULL);
-          g_free (extended_text);
-        }
-        gst_structure_id_take_value (event, QUARK_EXTENDED_ITEMS,
-            &extended_items);
-        g_array_free (extended_event_descriptors, TRUE);
-      }
-
-      component_descriptors = gst_mpeg_descriptor_find_all (&mpegdescriptor,
-          DESC_DVB_COMPONENT);
-      if (component_descriptors) {
-        int i;
-        guint8 *comp_descriptor;
-        GValue components = { 0 };
-        g_value_init (&components, GST_TYPE_LIST);
-        /* FIXME: do the component descriptor parsing less verbosely
-         * and better...a task for 0.10.6 */
-        for (i = 0; i < component_descriptors->len; i++) {
-          GstStructure *component = NULL;
-          GValue component_value = { 0 };
-          gint widescreen = 0;  /* 0 for 4:3, 1 for 16:9, 2 for > 16:9 */
-          gint freq = 25;       /* 25 or 30 measured in Hertz */
-          /* gboolean highdef = FALSE; */
-          gboolean panvectors = FALSE;
-          const gchar *comptype = "";
-
-          comp_descriptor = g_array_index (component_descriptors, guint8 *, i);
-          switch (DESC_DVB_COMPONENT_stream_content (comp_descriptor)) {
-            case 0x01:
-              /* video */
-              switch (DESC_DVB_COMPONENT_type (comp_descriptor)) {
-                case 0x01:
-                  widescreen = 0;
-                  freq = 25;
-                  break;
-                case 0x02:
-                  widescreen = 1;
-                  panvectors = TRUE;
-                  freq = 25;
-                  break;
-                case 0x03:
-                  widescreen = 1;
-                  panvectors = FALSE;
-                  freq = 25;
-                  break;
-                case 0x04:
-                  widescreen = 2;
-                  freq = 25;
-                  break;
-                case 0x05:
-                  widescreen = 0;
-                  freq = 30;
-                  break;
-                case 0x06:
-                  widescreen = 1;
-                  panvectors = TRUE;
-                  freq = 30;
-                  break;
-                case 0x07:
-                  widescreen = 1;
-                  panvectors = FALSE;
-                  freq = 30;
-                  break;
-                case 0x08:
-                  widescreen = 2;
-                  freq = 30;
-                  break;
-                case 0x09:
-                  widescreen = 0;
-                  /* highdef = TRUE; */
-                  freq = 25;
-                  break;
-                case 0x0A:
-                  widescreen = 1;
-                  /* highdef = TRUE; */
-                  panvectors = TRUE;
-                  freq = 25;
-                  break;
-                case 0x0B:
-                  widescreen = 1;
-                  /* highdef = TRUE; */
-                  panvectors = FALSE;
-                  freq = 25;
-                  break;
-                case 0x0C:
-                  widescreen = 2;
-                  /* highdef = TRUE; */
-                  freq = 25;
-                  break;
-                case 0x0D:
-                  widescreen = 0;
-                  /* highdef = TRUE; */
-                  freq = 30;
-                  break;
-                case 0x0E:
-                  widescreen = 1;
-                  /* highdef = TRUE; */
-                  panvectors = TRUE;
-                  freq = 30;
-                  break;
-                case 0x0F:
-                  widescreen = 1;
-                  /* highdef = TRUE; */
-                  panvectors = FALSE;
-                  freq = 30;
-                  break;
-                case 0x10:
-                  widescreen = 2;
-                  /* highdef = TRUE; */
-                  freq = 30;
-                  break;
-              }
-              component = gst_structure_new ("video", "high-definition",
-                  G_TYPE_BOOLEAN, TRUE, "frequency", G_TYPE_INT, freq,
-                  "tag", G_TYPE_INT, DESC_DVB_COMPONENT_tag (comp_descriptor),
-                  NULL);
-              if (widescreen == 0) {
-                gst_structure_set (component, "aspect-ratio",
-                    G_TYPE_STRING, "4:3", NULL);
-              } else if (widescreen == 2) {
-                gst_structure_set (component, "aspect-ratio", G_TYPE_STRING,
-                    "> 16:9", NULL);
-              } else {
-                gst_structure_set (component, "aspect-ratio", G_TYPE_STRING,
-                    "16:9", "pan-vectors", G_TYPE_BOOLEAN, panvectors, NULL);
-              }
-              break;
-            case 0x02:         /* audio */
-              comptype = "undefined";
-              switch (DESC_DVB_COMPONENT_type (comp_descriptor)) {
-                case 0x01:
-                  comptype = "single channel mono";
-                  break;
-                case 0x02:
-                  comptype = "dual channel mono";
-                  break;
-                case 0x03:
-                  comptype = "stereo";
-                  break;
-                case 0x04:
-                  comptype = "multi-channel multi-lingual";
-                  break;
-                case 0x05:
-                  comptype = "surround";
-                  break;
-                case 0x40:
-                  comptype = "audio description for the visually impaired";
-                  break;
-                case 0x41:
-                  comptype = "audio for the hard of hearing";
-                  break;
-              }
-              component = gst_structure_new ("audio", "type", G_TYPE_STRING,
-                  comptype, "tag", G_TYPE_INT,
-                  DESC_DVB_COMPONENT_tag (comp_descriptor), NULL);
-              break;
-            case 0x03:         /* subtitles/teletext/vbi */
-              comptype = "reserved";
-              switch (DESC_DVB_COMPONENT_type (comp_descriptor)) {
-                case 0x01:
-                  comptype = "EBU Teletext subtitles";
-                  break;
-                case 0x02:
-                  comptype = "associated EBU Teletext";
-                  break;
-                case 0x03:
-                  comptype = "VBI data";
-                  break;
-                case 0x10:
-                  comptype = "Normal DVB subtitles";
-                  break;
-                case 0x11:
-                  comptype = "Normal DVB subtitles for 4:3";
-                  break;
-                case 0x12:
-                  comptype = "Normal DVB subtitles for 16:9";
-                  break;
-                case 0x13:
-                  comptype = "Normal DVB subtitles for 2.21:1";
-                  break;
-                case 0x20:
-                  comptype = "Hard of hearing DVB subtitles";
-                  break;
-                case 0x21:
-                  comptype = "Hard of hearing DVB subtitles for 4:3";
-                  break;
-                case 0x22:
-                  comptype = "Hard of hearing DVB subtitles for 16:9";
-                  break;
-                case 0x23:
-                  comptype = "Hard of hearing DVB subtitles for 2.21:1";
-                  break;
-              }
-              component = gst_structure_new ("teletext", "type", G_TYPE_STRING,
-                  comptype, "tag", G_TYPE_INT,
-                  DESC_DVB_COMPONENT_tag (comp_descriptor), NULL);
-              break;
-          }
-          if (component) {
-            g_value_init (&component_value, GST_TYPE_STRUCTURE);
-            g_value_take_boxed (&component_value, component);
-            gst_value_list_append_and_take_value (&components,
-                &component_value);
-            component = NULL;
-          }
-        }
-        gst_structure_take_value (event, "components", &components);
-        g_array_free (component_descriptors, TRUE);
-      }
-
-      descriptors = mpegts_packetizer_parse_descriptors (packetizer,
-          &data, data + descriptors_loop_length);
-      if (!descriptors) {
-        gst_structure_free (event);
-        goto error;
-      }
-      set_descriptors_array_on_structure (event, QUARK_DESCRIPTORS,
-          descriptors);
-    }
-
-    g_value_init (&event_value, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&event_value, event);
-    gst_value_list_append_and_take_value (&events, &event_value);
-  }
-
-  if (data != end - 4) {
-    GST_WARNING ("PID %d invalid EIT parsed %d length %d",
-        section->pid, (gint) (data - section->data), section->section_length);
-    goto error;
-  }
-
-  gst_structure_id_take_value (eit, QUARK_EVENTS, &events);
-
-  GST_DEBUG ("EIT %" GST_PTR_FORMAT, eit);
-
-  return eit;
-
-error:
-  if (eit)
-    gst_structure_free (eit);
-
-  if (GST_VALUE_HOLDS_LIST (&events))
-    g_value_unset (&events);
-
-  return NULL;
-}
-
-static GstStructure *
-parse_tdt_tot_common (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section, GQuark name)
-{
-  GstStructure *res;
-  guint16 mjd;
-  guint year, month, day, hour, minute, second;
-  guint8 *data, *utc_ptr;
-
-  /* length at least 8 */
-  if (section->section_length < 8) {
-    GST_WARNING ("PID %d invalid TDT/TOT size %d",
-        section->pid, section->section_length);
-    return NULL;
-  }
-
-  data = section->data;
-  data += 3;
-
-  mjd = GST_READ_UINT16_BE (data);
-  data += 2;
-  utc_ptr = data;
-  if (mjd == G_MAXUINT16) {
-    year = 1900;
-    month = day = hour = minute = second = 0;
-  } else {
-    /* See EN 300 468 Annex C */
-    year = (guint32) (((mjd - 15078.2) / 365.25));
-    month = (guint8) ((mjd - 14956.1 - (guint) (year * 365.25)) / 30.6001);
-    day = mjd - 14956 - (guint) (year * 365.25) - (guint) (month * 30.6001);
-    if (month == 14 || month == 15) {
-      year++;
-      month = month - 1 - 12;
-    } else {
-      month--;
-    }
-    year += 1900;
-    hour = ((utc_ptr[0] & 0xF0) >> 4) * 10 + (utc_ptr[0] & 0x0F);
-    minute = ((utc_ptr[1] & 0xF0) >> 4) * 10 + (utc_ptr[1] & 0x0F);
-    second = ((utc_ptr[2] & 0xF0) >> 4) * 10 + (utc_ptr[2] & 0x0F);
-  }
-  res = gst_structure_new_id (name,
-      QUARK_YEAR, G_TYPE_UINT, year,
-      QUARK_MONTH, G_TYPE_UINT, month,
-      QUARK_DAY, G_TYPE_UINT, day,
-      QUARK_HOUR, G_TYPE_UINT, hour,
-      QUARK_MINUTE, G_TYPE_UINT, minute, QUARK_SECOND, G_TYPE_UINT, second,
-      NULL);
-
-  return res;
-}
-
-GstStructure *
-mpegts_packetizer_parse_tdt (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
-{
-  GstStructure *tdt = NULL;
-  GST_DEBUG ("TDT");
-
-  tdt = parse_tdt_tot_common (packetizer, section, QUARK_TDT);
-
-  return tdt;
-}
-
-GstStructure *
-mpegts_packetizer_parse_tot (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerSection * section)
-{
-  guint8 *data;
-  GstStructure *tot = NULL;
-  GValueArray *descriptors;
-  guint16 desc_len;
-
-  GST_DEBUG ("TOT");
-
-  tot = parse_tdt_tot_common (packetizer, section, QUARK_TOT);
-  data = section->data + 8;
-
-  desc_len = ((*data++) & 0xf) << 8;
-  desc_len |= *data++;
-  descriptors =
-      mpegts_packetizer_parse_descriptors (packetizer, &data, data + desc_len);
-  if (!descriptors) {
-    gst_structure_free (tot);
-    return NULL;
-  }
-  gst_structure_id_set (tot, QUARK_DESCRIPTORS, G_TYPE_VALUE_ARRAY, descriptors,
-      NULL);
-  g_value_array_free (descriptors);
-
-  return tot;
-}
-
-void
-mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer)
-{
-  if (packetizer->know_packet_size) {
-    packetizer->know_packet_size = FALSE;
-    packetizer->packet_size = 0;
-    if (packetizer->caps != NULL) {
-      gst_caps_unref (packetizer->caps);
-      packetizer->caps = NULL;
-    }
-  }
-  if (packetizer->streams) {
-    int i;
-    for (i = 0; i < 8192; i++) {
-      if (packetizer->streams[i]) {
-        mpegts_packetizer_stream_free (packetizer->streams[i]);
-      }
-    }
-    memset (packetizer->streams, 0, 8192 * sizeof (MpegTSPacketizerStream *));
-  }
-
-  gst_adapter_clear (packetizer->adapter);
-  packetizer->offset = 0;
-  packetizer->empty = TRUE;
-  packetizer->priv->available = 0;
-  packetizer->priv->mapped = NULL;
-  packetizer->priv->mapped_size = 0;
-  packetizer->priv->offset = 0;
-  packetizer->priv->last_in_time = GST_CLOCK_TIME_NONE;
-}
-
-void
-mpegts_packetizer_flush (MpegTSPacketizer2 * packetizer, gboolean hard)
-{
-  GST_DEBUG ("Flushing");
-
-  if (packetizer->streams) {
-    int i;
-    for (i = 0; i < 8192; i++) {
-      if (packetizer->streams[i]) {
-        mpegts_packetizer_clear_section (packetizer->streams[i]);
-      }
-    }
-  }
-  gst_adapter_clear (packetizer->adapter);
-
-  packetizer->offset = 0;
-  packetizer->empty = TRUE;
-  packetizer->priv->available = 0;
-  packetizer->priv->mapped = NULL;
-  packetizer->priv->offset = 0;
-  packetizer->priv->mapped_size = 0;
-  packetizer->priv->last_in_time = GST_CLOCK_TIME_NONE;
-  if (hard) {
-    /* For pull mode seeks in tsdemux the observation must be preserved */
-    flush_observations (packetizer);
-  }
-}
-
-void
-mpegts_packetizer_remove_stream (MpegTSPacketizer2 * packetizer, gint16 pid)
-{
-  MpegTSPacketizerStream *stream = packetizer->streams[pid];
-  if (stream) {
-    GST_INFO ("Removing stream for PID %d", pid);
-    mpegts_packetizer_stream_free (stream);
-    packetizer->streams[pid] = NULL;
-  }
-}
-
-MpegTSPacketizer2 *
-mpegts_packetizer_new (void)
-{
-  MpegTSPacketizer2 *packetizer;
-
-  packetizer =
-      GST_MPEGTS_PACKETIZER (g_object_new (GST_TYPE_MPEGTS_PACKETIZER, NULL));
-
-  return packetizer;
-}
-
-void
-mpegts_packetizer_push (MpegTSPacketizer2 * packetizer, GstBuffer * buffer)
-{
-  if (G_UNLIKELY (packetizer->empty)) {
-    packetizer->empty = FALSE;
-    packetizer->offset = GST_BUFFER_OFFSET (buffer);
-  }
-
-  GST_DEBUG ("Pushing %" G_GSIZE_FORMAT " byte from offset %" G_GUINT64_FORMAT,
-      gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer));
-  gst_adapter_push (packetizer->adapter, buffer);
-  packetizer->priv->available += gst_buffer_get_size (buffer);
-  /* If buffer timestamp is valid, store it */
-  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)))
-    packetizer->priv->last_in_time = GST_BUFFER_TIMESTAMP (buffer);
-}
-
-static gboolean
-mpegts_try_discover_packet_size (MpegTSPacketizer2 * packetizer)
-{
-  guint8 *dest;
-  int i, pos = -1, j;
-  static const guint psizes[] = {
-    MPEGTS_NORMAL_PACKETSIZE,
-    MPEGTS_M2TS_PACKETSIZE,
-    MPEGTS_DVB_ASI_PACKETSIZE,
-    MPEGTS_ATSC_PACKETSIZE
-  };
-
-
-  dest = g_malloc (MPEGTS_MAX_PACKETSIZE * 4);
-  /* wait for 3 sync bytes */
-  while (packetizer->priv->available >= MPEGTS_MAX_PACKETSIZE * 4) {
-
-    /* check for sync bytes */
-    gst_adapter_copy (packetizer->adapter, dest, 0, MPEGTS_MAX_PACKETSIZE * 4);
-    /* find first sync byte */
-    pos = -1;
-    for (i = 0; i < MPEGTS_MAX_PACKETSIZE; i++) {
-      if (dest[i] == PACKET_SYNC_BYTE) {
-        for (j = 0; j < 4; j++) {
-          guint packetsize = psizes[j];
-          /* check each of the packet size possibilities in turn */
-          if (dest[i] == PACKET_SYNC_BYTE
-              && dest[i + packetsize] == PACKET_SYNC_BYTE
-              && dest[i + packetsize * 2] == PACKET_SYNC_BYTE
-              && dest[i + packetsize * 3] == PACKET_SYNC_BYTE) {
-            packetizer->know_packet_size = TRUE;
-            packetizer->packet_size = packetsize;
-            packetizer->caps = gst_caps_new_simple ("video/mpegts",
-                "systemstream", G_TYPE_BOOLEAN, TRUE,
-                "packetsize", G_TYPE_INT, packetsize, NULL);
-            if (packetsize == MPEGTS_M2TS_PACKETSIZE)
-              pos = i - 4;
-            else
-              pos = i;
-            break;
-          }
-        }
-        break;
-      }
-    }
-
-    if (packetizer->know_packet_size)
-      break;
-
-    /* Skip MPEGTS_MAX_PACKETSIZE */
-    gst_adapter_flush (packetizer->adapter, MPEGTS_MAX_PACKETSIZE);
-    packetizer->priv->available -= MPEGTS_MAX_PACKETSIZE;
-    packetizer->offset += MPEGTS_MAX_PACKETSIZE;
-  }
-
-  g_free (dest);
-
-  if (packetizer->know_packet_size) {
-    GST_DEBUG ("have packetsize detected: %d of %u bytes",
-        packetizer->know_packet_size, packetizer->packet_size);
-    /* flush to sync byte */
-    if (pos > 0) {
-      GST_DEBUG ("Flushing out %d bytes", pos);
-      gst_adapter_flush (packetizer->adapter, pos);
-      packetizer->offset += pos;
-      packetizer->priv->available -= MPEGTS_MAX_PACKETSIZE;
-    }
-  } else {
-    /* drop invalid data and move to the next possible packets */
-    GST_DEBUG ("Could not determine packet size");
-  }
-
-  return packetizer->know_packet_size;
-}
-
-gboolean
-mpegts_packetizer_has_packets (MpegTSPacketizer2 * packetizer)
-{
-  if (G_UNLIKELY (packetizer->know_packet_size == FALSE)) {
-    if (!mpegts_try_discover_packet_size (packetizer))
-      return FALSE;
-  }
-  return packetizer->priv->available >= packetizer->packet_size;
-}
-
-MpegTSPacketizerPacketReturn
-mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerPacket * packet)
-{
-  MpegTSPacketizerPrivate *priv = packetizer->priv;
-  guint skip;
-  guint sync_offset;
-
-  if (G_UNLIKELY (!packetizer->know_packet_size)) {
-    if (!mpegts_try_discover_packet_size (packetizer))
-      return PACKET_NEED_MORE;
-  }
-
-  while (priv->available >= packetizer->packet_size) {
-    if (priv->mapped == NULL) {
-      priv->mapped_size = priv->available;
-      priv->mapped =
-          (guint8 *) gst_adapter_map (packetizer->adapter, priv->mapped_size);
-      priv->offset = 0;
-    }
-
-    /* M2TS packets don't start with the sync byte, all other variants do */
-    sync_offset = priv->offset;
-    if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE)
-      sync_offset += 4;
+    /* M2TS packets don't start with the sync byte, all other variants do */
+    sync_offset = priv->offset;
+    if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE)
+      sync_offset += 4;
 
     /* Check sync byte */
     if (G_LIKELY (priv->mapped[sync_offset] == 0x47)) {
@@ -2775,160 +831,243 @@ mpegts_packetizer_clear_packet (MpegTSPacketizer2 * packetizer,
   }
 }
 
-gboolean
+/*
+ * Ideally it should just return a section if:
+ * * The section is complete
+ * * The section is valid (sanity checks for length for example)
+ * * The section applies now (current_next_indicator)
+ * * The section is an update or was never seen
+ *
+ * The section should be a new GstMpegTSSection:
+ * * properly initialized
+ * * With pid, table_id AND section_type set (move logic from mpegtsbase)
+ * * With data copied into it (yes, minor overhead)
+ *
+ * In all other cases it should just return NULL
+ * */
+GstMpegTSSection *
 mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer,
-    MpegTSPacketizerPacket * packet, MpegTSPacketizerSection * section)
+    MpegTSPacketizerPacket * packet)
 {
-  gboolean res = FALSE;
+  GstMpegTSSection *res = NULL;
   MpegTSPacketizerStream *stream;
+  gboolean long_packet;
   guint8 pointer, table_id;
 #ifndef GST_DISABLE_GST_DEBUG
-  guint16 subtable_extension;
+  guint16 subtable_extension = 0;
 #endif
   guint section_length;
   guint8 *data, *data_start;
+  guint8 packet_cc;
 
   data = packet->data;
-  section->pid = packet->pid;
+  packet_cc = FLAGS_CONTINUITY_COUNTER (packet->scram_afc_cc);
+
+  GST_MEMDUMP ("section data", packet->data, packet->data_end - packet->data);
 
+  /* FIXME: If pointer is different from zero, this means the data should be accumulated
+   * to the previous section ! */
   if (packet->payload_unit_start_indicator) {
     pointer = *data++;
+    /* Sanity check for enough data */
     if (data + pointer > packet->data_end) {
-      GST_WARNING ("PID 0x%04x PSI section pointer points past the end "
+      GST_DEBUG ("PID 0x%04x PSI section pointer points past the end "
           "of the buffer", packet->pid);
       goto out;
     }
+    if (G_UNLIKELY (pointer != 0)) {
+      GST_FIXME ("PID 0x%04x PSI pointer %d != 0. Handle previous data",
+          packet->pid, pointer);
+      GST_MEMDUMP ("previous data", data, pointer);
+    }
 
     data += pointer;
   }
 
-  GST_MEMDUMP ("section data", packet->data, packet->data_end - packet->data);
-
-  /* TDT and TOT sections (see ETSI EN 300 468 5.2.5)
-   *  these sections do not extend to several packets so we don't need to use the
-   *  sections filter. */
-  if (packet->pid == 0x14) {
-    section->offset = packet->offset;
-    table_id = data[0];
-    section->section_length = (GST_READ_UINT24_BE (data) & 0x000FFF) + 3;
+  /*
+   * section_syntax_indicator means that the header is of the following format:
+   * * table_id (8bit)
+   * * section_syntax_indicator (1bit) == 0
+   * * reserved/private fields (3bit)
+   * * section_length (12bit)
+   * * data (of size section_length)
+   * * NO CRC !
+   */
+  long_packet = data[1] & 0x80;
+
+  /* Fast path for short packets */
+  if (!long_packet && packet->payload_unit_start_indicator) {
+    /* We can create the section now (function will check for size) */
+    GST_DEBUG ("Short packet");
+    section_length = (GST_READ_UINT16_BE (data + 1) & 0xfff) + 3;
+    /* Only do fast-path if we have enough byte */
+    if (section_length < packet->data_end - data) {
+      res =
+          gst_mpegts_section_new (packet->pid, g_memdup (data,
+              section_length), section_length);
+      if (data[section_length] != 0xff) {
+        GST_FIXME
+            ("Potentially more data after short section (report in bug #677443)");
+        GST_MEMDUMP ("Remainder", data + section_length,
+            packet->data_end - data - section_length);
 
-    if (data + section->section_length > packet->data_end) {
-      GST_WARNING ("PID 0x%04x PSI section length extends past the end "
-          "of the buffer", packet->pid);
+      }
+      if (res)
+        res->offset = packet->offset;
+      /* And exit */
       goto out;
     }
-    section->data = data;
-    section->table_id = table_id;
-    section->complete = TRUE;
-    res = TRUE;
-    GST_DEBUG ("TDT section pid:0x%04x table_id:0x%02x section_length: %d",
-        packet->pid, table_id, section->section_length);
-    goto out;
+    /* We don't have enough bytes to do short section shortcut */
   }
 
   data_start = data;
 
+  /* Get our filter */
   stream = packetizer->streams[packet->pid];
-  if (stream == NULL) {
-    stream = mpegts_packetizer_stream_new ();
+  if (G_UNLIKELY (stream == NULL)) {
+    if (!packet->payload_unit_start_indicator) {
+      /* Early exit (we need to start with a section start) */
+      GST_DEBUG ("PID 0x%04x  waiting for section start", packet->pid);
+      goto out;
+    }
+    stream = mpegts_packetizer_stream_new (packet->pid);
     packetizer->streams[packet->pid] = stream;
   }
 
+  /* If not a new section, and we were expecting a new section or
+   * there is a discontinuity, bail out. */
+  if (!packet->payload_unit_start_indicator) {
+    if (stream->continuity_counter == CONTINUITY_UNSET) {
+      GST_DEBUG ("PID 0x%04x  waiting for section start", packet->pid);
+      goto out;
+    }
+    if ((stream->continuity_counter + 1) % 16 != packet_cc) {
+      GST_WARNING ("PID 0x%04x section discontinuity (%d vs %d)", packet->pid,
+          stream->continuity_counter, packet_cc);
+      mpegts_packetizer_clear_section (stream);
+      goto out;
+    }
+  }
+
   if (packet->payload_unit_start_indicator) {
+    guint8 version_number, section_number, last_section_number;
+
+    /* Beginning of a new section, do as much pre-parsing as possible */
+    /* table_id                        : 8  bit */
     table_id = *data++;
-#ifndef GST_DISABLE_GST_DEBUG
-    /* subtable_extension should be read from 4th and 5th bytes only if
-     * section_syntax_indicator is 1 */
-    if ((data[0] & 0x80) == 0)
-      subtable_extension = 0;
-    else
-      subtable_extension = GST_READ_UINT16_BE (data + 2);
-    GST_DEBUG ("pid: 0x%04x table_id 0x%02x sub_table_extension %d",
-        packet->pid, table_id, subtable_extension);
-#endif
 
+    /* section_syntax_indicator        : 1  bit
+     * other_fields (reserved)         : 3  bit
+     * section_length                  : 12 bit */
     section_length = (GST_READ_UINT16_BE (data) & 0x0FFF) + 3;
+    data += 2;
+
+    /* subtable_extension (always present, we are in a long section) */
+    /* subtable extension              : 16 bit */
+    subtable_extension = GST_READ_UINT16_BE (data);
+    data += 2;
 
-    if (stream->continuity_counter != CONTINUITY_UNSET) {
+    /* reserved                      : 2  bit
+     * version_number                : 5  bit
+     * current_next_indicator        : 1  bit */
+    /* Bail out now if current_next_indicator == 0 */
+    if (G_UNLIKELY (!data & 0x01)) {
       GST_DEBUG
-          ("PID 0x%04x table_id 0x%02x sub_table_extension %d payload_unit_start_indicator set but section "
-          "not complete (last_continuity: %d continuity: %d sec len %d",
-          packet->pid, table_id, subtable_extension, stream->continuity_counter,
-          packet->continuity_counter, section_length);
-      mpegts_packetizer_clear_section (stream);
-    } else {
+          ("PID 0x%04x table_id 0x%02x section does not apply (current_next_indicator == 0)",
+          packet->pid, table_id);
+      goto out;
+    }
+
+    version_number = *data++ >> 1 & 0x1f;
+    /* section_number                : 8  bit */
+    section_number = *data++;
+    /* last_section_number                : 8  bit */
+    last_section_number = *data++;
+
+    GST_DEBUG
+        ("PID 0x%04x table_id:0x%02x subtable_extension:0x%04x version_number:%d section_number:%d(last:%d)",
+        packet->pid, table_id, subtable_extension, version_number,
+        section_number, last_section_number);
+
+    /* Check as early as possible whether we already saw this section
+     * i.e. that we saw a subtable with:
+     * * same subtable_extension (might be zero)
+     * * same version_number
+     * * same last_section_number
+     * * same section_number was seen
+     */
+    if (seen_section_before (stream, table_id, subtable_extension,
+            version_number, section_number, last_section_number)) {
       GST_DEBUG
-          ("pusi set and new stream section is %d long and data we have is: %d",
-          section_length, (gint) (packet->data_end - packet->data));
+          ("PID 0x%04x Already processed table_id:0x%02x subtable_extension:0x%04x, version_number:%d, section_number:%d",
+          packet->pid, table_id, subtable_extension, version_number,
+          section_number);
+      goto out;
+    }
+    if (G_UNLIKELY (section_number > last_section_number)) {
+      GST_WARNING
+          ("PID 0x%04x corrupted packet (section_number:%d > last_section_number:%d)",
+          packet->pid, section_number, last_section_number);
+      goto out;
     }
-    stream->continuity_counter = packet->continuity_counter;
+
+    stream->continuity_counter = packet_cc;
+
+    /* Copy over already parsed values */
+    stream->table_id = table_id;
     stream->section_length = section_length;
+    stream->version_number = version_number;
+    stream->subtable_extension = subtable_extension;
+    stream->section_number = section_number;
+    stream->last_section_number = last_section_number;
 
     /* Create enough room to store chunks of sections, including FF padding */
-    if (stream->section_allocated == 0) {
-      stream->section_data = g_malloc (section_length + 188);
-      stream->section_allocated = section_length + 188;
-    } else if (G_UNLIKELY (stream->section_allocated < section_length + 188)) {
-      stream->section_data =
-          g_realloc (stream->section_data, section_length + 188);
-      stream->section_allocated = section_length + 188;
-    }
+    stream->section_allocated = stream->section_length + 188;
+    stream->section_data = g_malloc (stream->section_allocated);
     memcpy (stream->section_data, data_start, packet->data_end - data_start);
     stream->section_offset = packet->data_end - data_start;
 
-    stream->section_table_id = table_id;
     stream->offset = packet->offset;
-
-    res = TRUE;
-  } else if (stream->continuity_counter != CONTINUITY_UNSET &&
-      (packet->continuity_counter == stream->continuity_counter + 1 ||
-          (stream->continuity_counter == MAX_CONTINUITY &&
-              packet->continuity_counter == 0))) {
-    stream->continuity_counter = packet->continuity_counter;
+  } else {
+    /* valid continuation of an existing section */
+    stream->continuity_counter = packet_cc;
 
     memcpy (stream->section_data + stream->section_offset, data_start,
         packet->data_end - data_start);
     stream->section_offset += packet->data_end - data_start;
     GST_DEBUG ("Appending data (need %d, have %d)", stream->section_length,
         stream->section_offset);
-
-    res = TRUE;
-  } else {
-    if (stream->continuity_counter == CONTINUITY_UNSET)
-      GST_DEBUG ("PID 0x%04x waiting for pusi", packet->pid);
-    else
-      GST_DEBUG ("PID 0x%04x section discontinuity "
-          "(last_continuity: %d continuity: %d", packet->pid,
-          stream->continuity_counter, packet->continuity_counter);
-    mpegts_packetizer_clear_section (stream);
   }
 
-  if (res) {
-    /* we pushed some data in the section adapter, see if the section is
-     * complete now */
-
-    /* >= as sections can be padded and padding is not included in
-     * section_length */
-    if (stream->section_offset >= stream->section_length) {
-      res = mpegts_packetizer_parse_section_header (packetizer,
-          stream, section);
-
-      /* flush stuffing bytes */
-      mpegts_packetizer_clear_section (stream);
-    } else {
-      GST_DEBUG ("section not complete");
-      /* section not complete yet */
-      section->complete = FALSE;
+  /* we pushed some data in the section adapter, see if the section is
+   * complete now */
+  /* >= as sections can be padded and padding is not included in
+   * section_length */
+  if (stream->section_offset >= stream->section_length) {
+    GST_DEBUG ("PID 0x%04x Section complete (Got %d, need %d)",
+        stream->pid, stream->section_offset, stream->section_length);
+    /* Remainder of section data should be padding (0xff) */
+    /* Adding a warning so people can report it in the bug reported regarding
+     * multiple sections after another (still not seen any samples in the wild) */
+    if (stream->section_offset > stream->section_length &&
+        stream->section_data[stream->section_length] != 0xff) {
+      GST_FIXME ("Potentially more data after section (report in bug #677443)");
+      GST_MEMDUMP ("Remainder", stream->section_data + stream->section_length,
+          stream->section_offset - stream->section_length);
     }
+    res = mpegts_packetizer_parse_section_header (packetizer, stream);
+
+    /* flush stuffing bytes */
+    mpegts_packetizer_clear_section (stream);
   } else {
-    GST_WARNING ("section not complete");
-    section->complete = FALSE;
+    GST_DEBUG ("PID 0x%04x, section not complete (Got %d, need %d)",
+        stream->pid, stream->section_offset, stream->section_length);
   }
 
 out:
   packet->data = data;
 
-  GST_DEBUG ("result: %d complete: %d", res, section->complete);
+  GST_DEBUG ("result: %p", res);
 
   return res;
 }
@@ -2938,407 +1077,8 @@ _init_local (void)
 {
   GST_DEBUG_CATEGORY_INIT (mpegts_packetizer_debug, "mpegtspacketizer", 0,
       "MPEG transport stream parser");
-
-  QUARK_PAT = g_quark_from_string ("pat");
-  QUARK_TRANSPORT_STREAM_ID = g_quark_from_string ("transport-stream-id");
-  QUARK_PROGRAM_NUMBER = g_quark_from_string ("program-number");
-  QUARK_PID = g_quark_from_string ("pid");
-  QUARK_PROGRAMS = g_quark_from_string ("programs");
-
-  QUARK_CAT = g_quark_from_string ("cat");
-
-  QUARK_PMT = g_quark_from_string ("pmt");
-  QUARK_PCR_PID = g_quark_from_string ("pcr-pid");
-  QUARK_VERSION_NUMBER = g_quark_from_string ("version-number");
-  QUARK_DESCRIPTORS = g_quark_from_string ("descriptors");
-  QUARK_STREAM_TYPE = g_quark_from_string ("stream-type");
-  QUARK_STREAMS = g_quark_from_string ("streams");
-
-  QUARK_NIT = g_quark_from_string ("nit");
-  QUARK_NETWORK_ID = g_quark_from_string ("network-id");
-  QUARK_CURRENT_NEXT_INDICATOR = g_quark_from_string ("current-next-indicator");
-  QUARK_ACTUAL_NETWORK = g_quark_from_string ("actual-network");
-  QUARK_NETWORK_NAME = g_quark_from_string ("network-name");
-  QUARK_ORIGINAL_NETWORK_ID = g_quark_from_string ("original-network-id");
-  QUARK_TRANSPORTS = g_quark_from_string ("transports");
-  QUARK_TERRESTRIAL = g_quark_from_string ("terrestrial");
-  QUARK_CABLE = g_quark_from_string ("cable");
-  QUARK_FREQUENCY = g_quark_from_string ("frequency");
-  QUARK_MODULATION = g_quark_from_string ("modulation");
-  QUARK_BANDWIDTH = g_quark_from_string ("bandwidth");
-  QUARK_CONSTELLATION = g_quark_from_string ("constellation");
-  QUARK_HIERARCHY = g_quark_from_string ("hierarchy");
-  QUARK_CODE_RATE_HP = g_quark_from_string ("code-rate-hp");
-  QUARK_CODE_RATE_LP = g_quark_from_string ("code-rate-lp");
-  QUARK_GUARD_INTERVAL = g_quark_from_string ("guard-interval");
-  QUARK_TRANSMISSION_MODE = g_quark_from_string ("transmission-mode");
-  QUARK_OTHER_FREQUENCY = g_quark_from_string ("other-frequency");
-  QUARK_SYMBOL_RATE = g_quark_from_string ("symbol-rate");
-  QUARK_INNER_FEC = g_quark_from_string ("inner-fec");
-  QUARK_DELIVERY = g_quark_from_string ("delivery");
-  QUARK_CHANNELS = g_quark_from_string ("channels");
-  QUARK_LOGICAL_CHANNEL_NUMBER = g_quark_from_string ("logical-channel-number");
-
-  QUARK_SDT = g_quark_from_string ("sdt");
-  QUARK_ACTUAL_TRANSPORT_STREAM =
-      g_quark_from_string ("actual-transport-stream");
-  QUARK_SERVICES = g_quark_from_string ("services");
-
-  QUARK_EIT = g_quark_from_string ("eit");
-  QUARK_SERVICE_ID = g_quark_from_string ("service-id");
-  QUARK_PRESENT_FOLLOWING = g_quark_from_string ("present-following");
-  QUARK_SEGMENT_LAST_SECTION_NUMBER =
-      g_quark_from_string ("segment-last-section-number");
-  QUARK_LAST_TABLE_ID = g_quark_from_string ("last-table-id");
-  QUARK_EVENTS = g_quark_from_string ("events");
-  QUARK_NAME = g_quark_from_string ("name");
-  QUARK_DESCRIPTION = g_quark_from_string ("description");
-  QUARK_EXTENDED_ITEM = g_quark_from_string ("extended_item");
-  QUARK_EXTENDED_ITEMS = g_quark_from_string ("extended-items");
-  QUARK_TEXT = g_quark_from_string ("text");
-  QUARK_EXTENDED_TEXT = g_quark_from_string ("extended-text");
-  QUARK_EVENT_ID = g_quark_from_string ("event-id");
-  QUARK_YEAR = g_quark_from_string ("year");
-  QUARK_MONTH = g_quark_from_string ("month");
-  QUARK_DAY = g_quark_from_string ("day");
-  QUARK_HOUR = g_quark_from_string ("hour");
-  QUARK_MINUTE = g_quark_from_string ("minute");
-  QUARK_SECOND = g_quark_from_string ("second");
-  QUARK_DURATION = g_quark_from_string ("duration");
-  QUARK_RUNNING_STATUS = g_quark_from_string ("running-status");
-  QUARK_FREE_CA_MODE = g_quark_from_string ("free-ca-mode");
-  QUARK_TDT = g_quark_from_string ("tdt");
-  QUARK_TOT = g_quark_from_string ("tot");
-}
-
-/**
- * @text: The text you want to get the encoding from
- * @start_text: Location where the beginning of the actual text is stored
- * @is_multibyte: Location where information whether it's a multibyte encoding
- * or not is stored
- * @returns: GIconv for conversion or NULL
- */
-static LocalIconvCode
-get_encoding (MpegTSPacketizer2 * packetizer, const gchar * text,
-    guint * start_text, gboolean * is_multibyte)
-{
-  LocalIconvCode encoding;
-  guint8 firstbyte;
-
-  *is_multibyte = FALSE;
-  *start_text = 0;
-
-  firstbyte = (guint8) text[0];
-
-  /* A wrong value */
-  g_return_val_if_fail (firstbyte != 0x00, _ICONV_UNKNOWN);
-
-  if (firstbyte <= 0x0B) {
-    /* 0x01 => iso 8859-5 */
-    encoding = firstbyte + _ICONV_ISO8859_4;
-    *start_text = 1;
-    goto beach;
-  }
-
-  /* ETSI EN 300 468, "Selection of character table" */
-  switch (firstbyte) {
-    case 0x0C:
-    case 0x0D:
-    case 0x0E:
-    case 0x0F:
-      /* RESERVED */
-      encoding = _ICONV_UNKNOWN;
-      break;
-    case 0x10:
-    {
-      guint16 table;
-
-      table = GST_READ_UINT16_BE (text + 1);
-
-      if (table < 17)
-        encoding = _ICONV_UNKNOWN + table;
-      else
-        encoding = _ICONV_UNKNOWN;;
-      *start_text = 3;
-      break;
-    }
-    case 0x11:
-      encoding = _ICONV_ISO10646_UC2;
-      *start_text = 1;
-      *is_multibyte = TRUE;
-      break;
-    case 0x12:
-      /*  EUC-KR implements KSX1001 */
-      encoding = _ICONV_EUC_KR;
-      *start_text = 1;
-      *is_multibyte = TRUE;
-      break;
-    case 0x13:
-      encoding = _ICONV_GB2312;
-      *start_text = 1;
-      break;
-    case 0x14:
-      encoding = _ICONV_UTF_16BE;
-      *start_text = 1;
-      *is_multibyte = TRUE;
-      break;
-    case 0x15:
-      /* TODO : Where does this come from ?? */
-      encoding = _ICONV_ISO10646_UTF8;
-      *start_text = 1;
-      break;
-    case 0x16:
-    case 0x17:
-    case 0x18:
-    case 0x19:
-    case 0x1A:
-    case 0x1B:
-    case 0x1C:
-    case 0x1D:
-    case 0x1E:
-    case 0x1F:
-      /* RESERVED */
-      encoding = _ICONV_UNKNOWN;
-      break;
-    default:
-      encoding = _ICONV_ISO6937;
-      break;
-  }
-
-beach:
-  GST_DEBUG
-      ("Found encoding %d, first byte is 0x%02x, start_text: %u, is_multibyte: %d",
-      encoding, firstbyte, *start_text, *is_multibyte);
-
-  return encoding;
-}
-
-/**
- * @text: The text to convert. It may include pango markup (<b> and </b>)
- * @length: The length of the string -1 if it's nul-terminated
- * @start: Where to start converting in the text
- * @encoding: The encoding of text
- * @is_multibyte: Whether the encoding is a multibyte encoding
- * @error: The location to store the error, or NULL to ignore errors
- * @returns: UTF-8 encoded string
- *
- * Convert text to UTF-8.
- */
-static gchar *
-convert_to_utf8 (const gchar * text, gint length, guint start,
-    GIConv iconv, gboolean is_multibyte, GError ** error)
-{
-  gchar *new_text;
-  gchar *tmp, *pos;
-  gint i;
-
-  text += start;
-
-  pos = tmp = g_malloc (length * 2);
-
-  if (is_multibyte) {
-    if (length == -1) {
-      while (*text != '\0') {
-        guint16 code = GST_READ_UINT16_BE (text);
-
-        switch (code) {
-          case 0xE086:         /* emphasis on */
-          case 0xE087:         /* emphasis off */
-            /* skip it */
-            break;
-          case 0xE08A:{
-            pos[0] = 0x00;      /* 0x00 0x0A is a new line */
-            pos[1] = 0x0A;
-            pos += 2;
-            break;
-          }
-          default:
-            pos[0] = text[0];
-            pos[1] = text[1];
-            pos += 2;
-            break;
-        }
-
-        text += 2;
-      }
-    } else {
-      for (i = 0; i < length; i += 2) {
-        guint16 code = GST_READ_UINT16_BE (text);
-
-        switch (code) {
-          case 0xE086:         /* emphasis on */
-          case 0xE087:         /* emphasis off */
-            /* skip it */
-            break;
-          case 0xE08A:{
-            pos[0] = 0x00;      /* 0x00 0x0A is a new line */
-            pos[1] = 0x0A;
-            pos += 2;
-            break;
-          }
-          default:
-            pos[0] = text[0];
-            pos[1] = text[1];
-            pos += 2;
-            break;
-        }
-
-        text += 2;
-      }
-    }
-  } else {
-    if (length == -1) {
-      while (*text != '\0') {
-        guint8 code = (guint8) (*text);
-
-        switch (code) {
-          case 0x86:           /* emphasis on */
-          case 0x87:           /* emphasis off */
-            /* skip it */
-            break;
-          case 0x8A:
-            *pos = '\n';
-            pos += 1;
-            break;
-          default:
-            *pos = *text;
-            pos += 1;
-            break;
-        }
-
-        text++;
-      }
-    } else {
-      for (i = 0; i < length; i++) {
-        guint8 code = (guint8) (*text);
-
-        switch (code) {
-          case 0x86:           /* emphasis on */
-          case 0x87:           /* emphasis off */
-            /* skip it */
-            break;
-          case 0x8A:
-            *pos = '\n';
-            pos += 1;
-            break;
-          default:
-            *pos = *text;
-            pos += 1;
-            break;
-        }
-
-        text++;
-      }
-    }
-  }
-
-  if (pos > tmp) {
-    gsize bread = 0;
-
-    new_text =
-        g_convert_with_iconv (tmp, pos - tmp, iconv, &bread, NULL, error);
-    GST_DEBUG ("Converted to : %s", new_text);
-  } else {
-    new_text = g_strdup ("");
-  }
-
-  g_free (tmp);
-
-  return new_text;
 }
 
-static gchar *
-get_encoding_and_convert (MpegTSPacketizer2 * packetizer, const gchar * text,
-    guint length)
-{
-  GError *error = NULL;
-  gchar *converted_str;
-  guint start_text = 0;
-  gboolean is_multibyte;
-  LocalIconvCode encoding;
-  GIConv iconv = (GIConv) - 1;
-
-  g_return_val_if_fail (text != NULL, NULL);
-
-  if (text == NULL || length == 0)
-    return g_strdup ("");
-
-  encoding = get_encoding (packetizer, text, &start_text, &is_multibyte);
-
-  if (encoding > _ICONV_UNKNOWN && encoding < _ICONV_MAX) {
-    GST_DEBUG ("Encoding %s", iconvtablename[encoding]);
-    if (packetizer->priv->iconvs[encoding] == (GIConv) - 1)
-      packetizer->priv->iconvs[encoding] =
-          g_iconv_open ("utf-8", iconvtablename[encoding]);
-    iconv = packetizer->priv->iconvs[encoding];
-  }
-
-  if (iconv == (GIConv) - 1) {
-    GST_WARNING ("Could not detect encoding");
-    converted_str = g_strndup (text, length);
-    goto beach;
-  }
-
-  converted_str = convert_to_utf8 (text, length - start_text, start_text,
-      iconv, is_multibyte, &error);
-  if (error != NULL) {
-    GST_WARNING ("Could not convert string: %s", error->message);
-    if (converted_str)
-      g_free (converted_str);
-    g_error_free (error);
-    error = NULL;
-
-    if (encoding >= _ICONV_ISO8859_2 && encoding <= _ICONV_ISO8859_15) {
-      /* Sometimes using the standard 8859-1 set fixes issues */
-      GST_DEBUG ("Encoding %s", iconvtablename[_ICONV_ISO8859_1]);
-      if (packetizer->priv->iconvs[_ICONV_ISO8859_1] == (GIConv) - 1)
-        packetizer->priv->iconvs[_ICONV_ISO8859_1] =
-            g_iconv_open ("utf-8", iconvtablename[_ICONV_ISO8859_1]);
-      iconv = packetizer->priv->iconvs[_ICONV_ISO8859_1];
-
-      GST_INFO ("Trying encoding ISO 8859-1");
-      converted_str = convert_to_utf8 (text, length, 1, iconv, FALSE, &error);
-      if (error != NULL) {
-        GST_WARNING
-            ("Could not convert string while assuming encoding ISO 8859-1: %s",
-            error->message);
-        g_error_free (error);
-        goto failed;
-      }
-    } else if (encoding == _ICONV_ISO6937) {
-
-      /* The first part of ISO 6937 is identical to ISO 8859-9, but
-       * they differ in the second part. Some channels don't
-       * provide the first byte that indicates ISO 8859-9 encoding.
-       * If decoding from ISO 6937 failed, we try ISO 8859-9 here.
-       */
-      if (packetizer->priv->iconvs[_ICONV_ISO8859_9] == (GIConv) - 1)
-        packetizer->priv->iconvs[_ICONV_ISO8859_9] =
-            g_iconv_open ("utf-8", iconvtablename[_ICONV_ISO8859_9]);
-      iconv = packetizer->priv->iconvs[_ICONV_ISO8859_9];
-
-      GST_INFO ("Trying encoding ISO 8859-9");
-      converted_str = convert_to_utf8 (text, length, 0, iconv, FALSE, &error);
-      if (error != NULL) {
-        GST_WARNING
-            ("Could not convert string while assuming encoding ISO 8859-9: %s",
-            error->message);
-        g_error_free (error);
-        goto failed;
-      }
-    } else
-      goto failed;
-  }
-
-beach:
-  return converted_str;
-
-failed:
-  {
-    text += start_text;
-    return g_strndup (text, length - start_text);
-  }
-}
 
 static void
 mpegts_packetizer_resync (MpegTSPCR * pcr, GstClockTime time,
@@ -3496,8 +1236,8 @@ calculate_skew (MpegTSPCR * pcr, guint64 pcrtime, GstClockTime time)
   } else
     send_diff = gstpcrtime - pcr->base_pcrtime;
 
-  GST_DEBUG ("gstpcr %" GST_TIME_FORMAT ", buftime %" GST_TIME_FORMAT ", base %"
-      GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT,
+  GST_DEBUG ("gstpcr %" GST_TIME_FORMAT ", buftime %" GST_TIME_FORMAT
+      ", base %" GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT,
       GST_TIME_ARGS (gstpcrtime), GST_TIME_ARGS (time),
       GST_TIME_ARGS (pcr->base_pcrtime), GST_TIME_ARGS (send_diff));
 
@@ -3528,9 +1268,10 @@ calculate_skew (MpegTSPCR * pcr, guint64 pcrtime, GstClockTime time)
   slope = recv_diff > 0 ? (send_diff * 8) / recv_diff : 8;
 #endif
 
-  GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", recv_diff %"
-      GST_TIME_FORMAT ", slope %" G_GUINT64_FORMAT, GST_TIME_ARGS (time),
-      GST_TIME_ARGS (pcr->base_time), GST_TIME_ARGS (recv_diff), slope);
+  GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT
+      ", recv_diff %" GST_TIME_FORMAT ", slope %" G_GUINT64_FORMAT,
+      GST_TIME_ARGS (time), GST_TIME_ARGS (pcr->base_time),
+      GST_TIME_ARGS (recv_diff), slope);
 
   /* if the difference between the sender timeline and the receiver timeline
    * changed too quickly we have to resync because the server likely restarted
@@ -3608,8 +1349,8 @@ calculate_skew (MpegTSPCR * pcr, guint64 pcrtime, GstClockTime time)
     }
     /* average the min values */
     pcr->skew = (pcr->window_min + (124 * pcr->skew)) / 125;
-    GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT, delta,
-        pcr->window_min);
+    GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT,
+        delta, pcr->window_min);
   }
   /* wrap around in the window */
   if (G_UNLIKELY (pos >= pcr->window_size))
@@ -3661,8 +1402,8 @@ no_skew:
 }
 
 static void
-record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable, guint64 pcr,
-    guint64 offset)
+record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable,
+    guint64 pcr, guint64 offset)
 {
   MpegTSPacketizerPrivate *priv = packetizer->priv;
 
@@ -3697,8 +1438,8 @@ mpegts_packetizer_get_seen_pcr (MpegTSPacketizer2 * packetizer)
 }
 
 GstClockTime
-mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, guint64 offset,
-    guint16 pid)
+mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer,
+    guint64 offset, guint16 pid)
 {
   MpegTSPacketizerPrivate *priv = packetizer->priv;
   MpegTSPCR *pcrtable;
@@ -3729,8 +1470,8 @@ mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, guint64 offset,
 }
 
 GstClockTime
-mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, GstClockTime pts,
-    guint16 pcr_pid)
+mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
+    GstClockTime pts, guint16 pcr_pid)
 {
   GstClockTime res = GST_CLOCK_TIME_NONE;
   MpegTSPCR *pcrtable = get_pcr_table (packetizer, pcr_pid);
@@ -3761,8 +1502,8 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, GstClockTime pts,
 }
 
 guint64
-mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer, GstClockTime ts,
-    guint16 pcr_pid)
+mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer,
+    GstClockTime ts, guint16 pcr_pid)
 {
   MpegTSPacketizerPrivate *priv = packetizer->priv;
   MpegTSPCR *pcrtable;
@@ -3784,8 +1525,8 @@ mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer, GstClockTime ts,
       pcrtable->last_pcr - pcrtable->first_pcr);
   res += pcrtable->first_offset + priv->refoffset;
 
-  GST_DEBUG ("Returning offset %" G_GUINT64_FORMAT " for ts %" GST_TIME_FORMAT,
-      res, GST_TIME_ARGS (ts));
+  GST_DEBUG ("Returning offset %" G_GUINT64_FORMAT " for ts %"
+      GST_TIME_FORMAT, res, GST_TIME_ARGS (ts));
 
   return res;
 }
index bdc6073..c1e75c3 100644 (file)
@@ -28,6 +28,7 @@
 #include <gst/base/gstadapter.h>
 #include <glib.h>
 
+#include <gst/mpegts/mpegts.h>
 #include "gstmpegdefs.h"
 
 #define MPEGTS_NORMAL_PACKETSIZE  188
@@ -62,18 +63,24 @@ typedef struct _MpegTSPacketizerPrivate MpegTSPacketizerPrivate;
 
 typedef struct
 {
+  guint16 pid;
   guint   continuity_counter;
 
-  /* Section data (reused) */
+  /* Section data (always newly allocated) */
   guint8 *section_data;
-  /* Expected length of the section */
-  guint   section_length;
   /* Allocated length of section_data */
   guint   section_allocated;
   /* Current offset in section_data */
   guint16 section_offset;
+
+  /* Values for pending section */
   /* table_id of the pending section_data */
-  guint8  section_table_id;
+  guint8  table_id;
+  guint   section_length;
+  guint8  version_number;
+  guint16 subtable_extension;
+  guint8  section_number;
+  guint8  last_section_number;
 
   GSList *subtables;
 
@@ -110,12 +117,16 @@ struct _MpegTSPacketizer2Class {
   GObjectClass object_class;
 };
 
+#define FLAGS_SCRAMBLED(f) (f & 0xc0)
+#define FLAGS_HAS_AFC(f) (f & 0x20)
+#define FLAGS_HAS_PAYLOAD(f) (f & 0x10)
+#define FLAGS_CONTINUITY_COUNTER(f) (f & 0x0f)
+
 typedef struct
 {
   gint16  pid;
   guint8  payload_unit_start_indicator;
-  guint8  adaptation_field_control;
-  guint8  continuity_counter;
+  guint8  scram_afc_cc;
   guint8 *payload;
 
   guint8 *data_start;
@@ -131,32 +142,23 @@ typedef struct
 
 typedef struct
 {
-  gboolean complete;
-  /* GstBuffer *buffer; */
-  guint8  *data;
-  guint    section_length;
-  guint64  offset;
-
-  gint16   pid;
-  guint8   table_id;
-  guint16  subtable_extension;
-  guint8   version_number;
-  guint8   current_next_indicator;
-
-  guint32  crc;
-} MpegTSPacketizerSection; 
-
-typedef struct
-{
   guint8 table_id;
   /* the spec says sub_table_extension is the fourth and fifth byte of a 
    * section when the section_syntax_indicator is set to a value of "1". If 
    * section_syntax_indicator is 0, sub_table_extension will be set to 0 */
-  guint16 subtable_extension;
-  guint8  version_number;
-  GList * crc;
+  guint16  subtable_extension;
+  guint8   version_number;
+  guint8   last_section_number;
+  /* table of bits, whether the section was seen or not.
+   * Use MPEGTS_BIT_* macros to check */
+  /* Size is 32, because there's a maximum of 256 (32*8) section_number */
+  guint8   seen_section[32];
 } MpegTSPacketizerStreamSubtable;
 
+#define MPEGTS_BIT_SET(field, offs)    ((field)[(offs) >> 3] |=  (1 << ((offs) & 0x7)))
+#define MPEGTS_BIT_UNSET(field, offs)  ((field)[(offs) >> 3] &= ~(1 << ((offs) & 0x7)))
+#define MPEGTS_BIT_IS_SET(field, offs) ((field)[(offs) >> 3] &   (1 << ((offs) & 0x7)))
+
 typedef enum {
   PACKET_BAD       = FALSE,
   PACKET_OK        = TRUE,
@@ -179,24 +181,8 @@ G_GNUC_INTERNAL void mpegts_packetizer_clear_packet (MpegTSPacketizer2 *packetiz
 G_GNUC_INTERNAL void mpegts_packetizer_remove_stream(MpegTSPacketizer2 *packetizer,
   gint16 pid);
 
-G_GNUC_INTERNAL gboolean mpegts_packetizer_push_section (MpegTSPacketizer2 *packetzer,
-  MpegTSPacketizerPacket *packet, MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_cat (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_pat (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_pmt (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_nit (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_sdt (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_eit (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_tdt (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
-G_GNUC_INTERNAL GstStructure *mpegts_packetizer_parse_tot (MpegTSPacketizer2 *packetizer,
-  MpegTSPacketizerSection *section);
+G_GNUC_INTERNAL GstMpegTSSection *mpegts_packetizer_push_section (MpegTSPacketizer2 *packetzer,
+  MpegTSPacketizerPacket *packet);
 
 /* Only valid if calculate_offset is TRUE */
 G_GNUC_INTERNAL guint mpegts_packetizer_get_seen_pcr (MpegTSPacketizer2 *packetizer);
index 5b2b6c7..979d6c9 100644 (file)
@@ -91,7 +91,7 @@ mpegts_parse_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program);
 
 static GstFlowReturn
 mpegts_parse_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
-    MpegTSPacketizerSection * section);
+    GstMpegTSSection * section);
 
 static MpegTSParsePad *mpegts_parse_create_tspad (MpegTSParse2 * parse,
     const gchar * name);
@@ -342,7 +342,7 @@ mpegts_parse_release_pad (GstElement * element, GstPad * pad)
 
 static GstFlowReturn
 mpegts_parse_tspad_push_section (MpegTSParse2 * parse, MpegTSParsePad * tspad,
-    MpegTSPacketizerSection * section, MpegTSPacketizerPacket * packet)
+    GstMpegTSSection * section, MpegTSPacketizerPacket * packet)
 {
   GstFlowReturn ret = GST_FLOW_OK;
   gboolean to_push = TRUE;
@@ -420,7 +420,7 @@ pad_clear_for_push (GstPad * pad, MpegTSParse2 * parse)
 
 static GstFlowReturn
 mpegts_parse_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
-    MpegTSPacketizerSection * section)
+    GstMpegTSSection * section)
 {
   MpegTSParse2 *parse = (MpegTSParse2 *) base;
   guint32 pads_cookie;
@@ -598,8 +598,6 @@ gst_mpegtsparse_plugin_init (GstPlugin * plugin)
   GST_DEBUG_CATEGORY_INIT (mpegts_parse_debug, "tsparse", 0,
       "MPEG transport stream parser");
 
-  gst_mpegtsdesc_init_debug ();
-
   return gst_element_register (plugin, "tsparse",
       GST_RANK_NONE, GST_TYPE_MPEGTS_PARSE);
 }
index 9c49c30..54417cf 100644 (file)
 
 G_BEGIN_DECLS
 
+
+/*
+ * PES stream_id assignments:
+ *
+ * 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                          0xB9
+#define ID_PS_PACK_START_CODE                   0xBA
+#define ID_PS_SYSTEM_HEADER_START_CODE          0xBB
+#define ID_PS_PROGRAM_STREAM_MAP                0xBC
+#define ID_PRIVATE_STREAM_1                     0xBD
+#define ID_PADDING_STREAM                       0xBE
+#define ID_PRIVATE_STREAM_2                     0xBF
+#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_0        0xC0
+#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_32       0xDF
+#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_0        0xE0
+#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_16       0xEF
+#define ID_ECM_STREAM                           0xF0
+#define ID_EMM_STREAM                           0xF1
+#define ID_DSMCC_STREAM                         0xF2
+#define ID_ISO_IEC_13522_STREAM                 0xF3
+#define ID_ITU_TREC_H222_TYPE_A_STREAM          0xF4
+#define ID_ITU_TREC_H222_TYPE_B_STREAM          0xF5
+#define ID_ITU_TREC_H222_TYPE_C_STREAM          0xF6
+#define ID_ITU_TREC_H222_TYPE_D_STREAM          0xF7
+#define ID_ITU_TREC_H222_TYPE_E_STREAM          0xF8
+#define ID_ANCILLARY_STREAM                     0xF9
+#define ID_14496_1_SL_PACKETIZED_STREAM         0xFA
+#define ID_14496_1_SL_FLEXMUX_STREAM            0xFB
+#define ID_METADATA_STREAM                      0xFC
+#define ID_EXTENDED_STREAM_ID                   0xFD
+#define ID_RESERVED_STREAM_3                    0xFE
+#define ID_PROGRAM_STREAM_DIRECTORY             0xFF
+
+/*
+ * PES stream_id_extension assignments (if stream_id == ID_EXTENDED_STREAM_ID)
+ *
+ *  000 0000             IPMP Control Information stream
+ *  000 0001             IPMP Stream
+ *  000 0010 - 001 0001  ISO/IEC 14496-17 text Streams
+ *  001 0010 - 010 0001  ISO/IEC 23002-3 auxiliary video data Streams
+ *  ... .... - 011 1111  Reserved
+ *
+ *  PRIVATE STREAM RANGES (But known as used)
+ *  101 0101 - 101 1111  VC-1
+ *  110 0000 - 110 1111  Dirac (VC-1)
+ *
+ *  111 0001             AC3 or independent sub-stream 0 of EAC3/DD+
+ *                       DTS or core sub-stream
+ *  111 0010             dependent sub-stream of EAC3/DD+
+ *                       DTS extension sub-stream
+ *                       Secondary EAC3/DD+
+ *                       Secondary DTS-HD LBR
+ *  111 0110             AC3 in MLP/TrueHD
+ *  1xx xxxx    private_stream
+ */
+#define EXT_ID_IPMP_CONTORL_INFORMATION_STREAM  0x00
+#define EXT_ID_IPMP_STREAM                     0x01
+
+/* VC-1 */
+#define EXT_ID_VC1_FIRST                       0x55
+#define EXT_ID_VC1_LAST                        0x5F
+
 typedef enum {
   PES_FLAG_PRIORITY            = 1 << 3,       /* PES_priority (present: high-priority) */
   PES_FLAG_DATA_ALIGNMENT      = 1 << 2,       /* data_alignment_indicator */
@@ -57,7 +142,7 @@ typedef enum {
 } PESParsingResult;
 
 typedef struct {
-  guint8       stream_id;      /* See ID_* in gstmpegdefs.h */
+  guint8       stream_id;      /* See ID_* above */
   guint16      packet_length;  /* The size of the PES header and PES data
                                 * (if 0 => unbounded packet) */
   guint16      header_size;    /* The complete size of the PES header */
index 7b1f6db..c876981 100644 (file)
@@ -227,7 +227,7 @@ gst_ts_demux_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program);
 static void gst_ts_demux_reset (MpegTSBase * base);
 static GstFlowReturn
 gst_ts_demux_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
-    MpegTSPacketizerSection * section);
+    GstMpegTSSection * section);
 static void gst_ts_demux_flush (MpegTSBase * base, gboolean hard);
 static void
 gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * stream,
@@ -634,15 +634,18 @@ done:
 static void
 gst_ts_demux_create_tags (TSDemuxStream * stream)
 {
-  guint8 *desc = NULL;
+  MpegTSBaseStream *bstream = (MpegTSBaseStream *) stream;
+  const guint8 *desc = NULL;
   int i;
 
-  desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-      DESC_ISO_639_LANGUAGE);
+  desc =
+      mpegts_get_descriptor_from_stream (bstream,
+      GST_MTS_DESC_ISO_639_LANGUAGE);
 
   if (!desc) {
-    desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-        DESC_DVB_SUBTITLING);
+    desc =
+        mpegts_get_descriptor_from_stream (bstream,
+        GST_MTS_DESC_DVB_SUBTITLING);
   }
 
   if (desc) {
@@ -674,8 +677,6 @@ gst_ts_demux_create_tags (TSDemuxStream * stream)
       gst_tag_list_add (stream->taglist, GST_TAG_MERGE_REPLACE,
           GST_TAG_LANGUAGE_CODE, (lc) ? lc : lang_code, NULL);
     }
-
-    g_free (desc);
   }
 }
 
@@ -687,7 +688,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
   gchar *name = NULL;
   GstCaps *caps = NULL;
   GstPadTemplate *template = NULL;
-  guint8 *desc = NULL;
+  const guint8 *desc = NULL;
   GstPad *pad = NULL;
 
   gst_ts_demux_create_tags (stream);
@@ -695,27 +696,31 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
   GST_LOG ("Attempting to create pad for stream 0x%04x with stream_type %d",
       bstream->pid, bstream->stream_type);
 
+  /* FIXME : Extract the registration descriptor in mpegtsbase for each
+   * program and stream. This will help provide cleaner detection of all the
+   * mpeg-ts variants (Bluray, HDV, ...) and "private" types (dirac, vc1,
+   * ac3, eac3, ... */
+
   /* First handle BluRay-specific stream types since there is some overlap
    * between BluRay and non-BluRay streay type identifiers */
-  desc = mpegts_get_descriptor_from_program (program, DESC_REGISTRATION);
+  desc =
+      mpegts_get_descriptor_from_program (program, GST_MTS_DESC_REGISTRATION);
   if (desc) {
     if (DESC_REGISTRATION_format_identifier (desc) == DRF_ID_HDMV) {
       switch (bstream->stream_type) {
         case ST_BD_AUDIO_AC3:
         {
-          guint8 *ac3_desc;
+          const guint8 *ac3_desc;
 
           /* ATSC ac3 audio descriptor */
           ac3_desc =
               mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-              DESC_AC3_AUDIO_STREAM);
+              GST_MTS_DESC_AC3_AUDIO_STREAM);
           if (ac3_desc && DESC_AC_AUDIO_STREAM_bsid (ac3_desc) != 16) {
             GST_LOG ("ac3 audio");
             template = gst_static_pad_template_get (&audio_template);
             name = g_strdup_printf ("audio_%04x", bstream->pid);
             caps = gst_caps_new_empty_simple ("audio/x-ac3");
-
-            g_free (ac3_desc);
           } else {
             template = gst_static_pad_template_get (&audio_template);
             name = g_strdup_printf ("audio_%04x", bstream->pid);
@@ -745,7 +750,6 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
           break;
       }
     }
-    g_free (desc);
   }
   if (template && name && caps)
     goto done;
@@ -755,6 +759,8 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
     case ST_VIDEO_MPEG1:
     case ST_VIDEO_MPEG2:
     case ST_PS_VIDEO_MPEG2_DCII:
+      /* FIXME : Use DCII registration code (ETV1 ?) to handle that special
+       * Stream type (ST_PS_VIDEO_MPEG2_DCII) */
       GST_LOG ("mpeg video");
       template = gst_static_pad_template_get (&video_template);
       name = g_strdup_printf ("video_%04x", bstream->pid);
@@ -775,51 +781,50 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
       break;
     case ST_PRIVATE_DATA:
       GST_LOG ("private data");
+      /* FIXME: Move all of this into a common method (there might be other
+       * types also, depending on registratino descriptors also
+       */
       desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_DVB_AC3);
+          GST_MTS_DESC_DVB_AC3);
       if (desc) {
         GST_LOG ("ac3 audio");
         template = gst_static_pad_template_get (&audio_template);
         name = g_strdup_printf ("audio_%04x", bstream->pid);
         caps = gst_caps_new_empty_simple ("audio/x-ac3");
-        g_free (desc);
         break;
       }
 
       desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_DVB_ENHANCED_AC3);
+          GST_MTS_DESC_DVB_ENHANCED_AC3);
       if (desc) {
         GST_LOG ("ac3 audio");
         template = gst_static_pad_template_get (&audio_template);
         name = g_strdup_printf ("audio_%04x", bstream->pid);
         caps = gst_caps_new_empty_simple ("audio/x-eac3");
-        g_free (desc);
         break;
       }
       desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_DVB_TELETEXT);
+          GST_MTS_DESC_DVB_TELETEXT);
       if (desc) {
         GST_LOG ("teletext");
         template = gst_static_pad_template_get (&private_template);
         name = g_strdup_printf ("private_%04x", bstream->pid);
         caps = gst_caps_new_empty_simple ("private/teletext");
-        g_free (desc);
         break;
       }
       desc =
           mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_DVB_SUBTITLING);
+          GST_MTS_DESC_DVB_SUBTITLING);
       if (desc) {
         GST_LOG ("subtitling");
         template = gst_static_pad_template_get (&private_template);
         name = g_strdup_printf ("private_%04x", bstream->pid);
         caps = gst_caps_new_empty_simple ("subpicture/x-dvb");
-        g_free (desc);
         break;
       }
 
       desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_REGISTRATION);
+          GST_MTS_DESC_REGISTRATION);
       if (desc) {
         switch (DESC_REGISTRATION_format_identifier (desc)) {
           case DRF_ID_DTS1:
@@ -837,7 +842,6 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
             caps = gst_caps_new_empty_simple ("audio/x-smpte-302m");
             break;
         }
-        g_free (desc);
       }
       if (template)
         break;
@@ -852,12 +856,14 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
       }
       break;
     case ST_HDV_AUX_V:
+      /* FIXME : Should only be used with specific PMT registration_descriptor */
       /* We don't expose those streams since they're only helper streams */
       /* template = gst_static_pad_template_get (&private_template); */
       /* name = g_strdup_printf ("private_%04x", bstream->pid); */
       /* caps = gst_caps_new_simple ("hdv/aux-v", NULL); */
       break;
     case ST_HDV_AUX_A:
+      /* FIXME : Should only be used with specific PMT registration_descriptor */
       /* We don't expose those streams since they're only helper streams */
       /* template = gst_static_pad_template_get (&private_template); */
       /* name = g_strdup_printf ("private_%04x", bstream->pid); */
@@ -903,7 +909,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
     case ST_VIDEO_DIRAC:
       desc =
           mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_REGISTRATION);
+          GST_MTS_DESC_REGISTRATION);
       if (desc) {
         if (DESC_LENGTH (desc) >= 4) {
           if (DESC_REGISTRATION_format_identifier (desc) == 0x64726163) {
@@ -914,7 +920,6 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
             caps = gst_caps_new_empty_simple ("video/x-dirac");
           }
         }
-        g_free (desc);
       }
       break;
     case ST_PRIVATE_EA:        /* Try to detect a VC1 stream */
@@ -922,14 +927,13 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
       gboolean is_vc1 = FALSE;
       desc =
           mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_REGISTRATION);
+          GST_MTS_DESC_REGISTRATION);
       if (desc) {
         if (DESC_LENGTH (desc) >= 4) {
           if (DESC_REGISTRATION_format_identifier (desc) == DRF_ID_VC1) {
             is_vc1 = TRUE;
           }
         }
-        g_free (desc);
       }
       if (!is_vc1) {
         GST_WARNING ("0xea private stream type found but no descriptor "
@@ -946,25 +950,22 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
     case ST_PS_AUDIO_AC3:
       /* DVB_ENHANCED_AC3 */
       desc = mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_DVB_ENHANCED_AC3);
+          GST_MTS_DESC_DVB_ENHANCED_AC3);
       if (desc) {
         template = gst_static_pad_template_get (&audio_template);
         name = g_strdup_printf ("audio_%04x", bstream->pid);
         caps = gst_caps_new_empty_simple ("audio/x-eac3");
-        g_free (desc);
         break;
       }
 
       /* DVB_AC3 */
       desc =
           mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
-          DESC_DVB_AC3);
+          GST_MTS_DESC_DVB_AC3);
       if (!desc)
         GST_WARNING ("AC3 stream type found but no corresponding "
             "descriptor to differentiate between AC3 and EAC3. "
             "Assuming plain AC3.");
-      else
-        g_free (desc);
       template = gst_static_pad_template_get (&audio_template);
       name = g_strdup_printf ("audio_%04x", bstream->pid);
       caps = gst_caps_new_empty_simple ("audio/x-ac3");
@@ -1295,6 +1296,7 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream,
 {
   guint8 *data;
   guint size;
+  guint8 cc = FLAGS_CONTINUITY_COUNTER (packet->scram_afc_cc);
 
   GST_LOG ("pid: 0x%04x state:%d", stream->stream.pid, stream->state);
 
@@ -1302,17 +1304,16 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream,
   data = packet->payload;
 
   if (stream->continuity_counter == CONTINUITY_UNSET) {
-    GST_DEBUG ("CONTINUITY: Initialize to %d", packet->continuity_counter);
-  } else if ((packet->continuity_counter == stream->continuity_counter + 1 ||
-          (stream->continuity_counter == MAX_CONTINUITY &&
-              packet->continuity_counter == 0))) {
-    GST_LOG ("CONTINUITY: Got expected %d", packet->continuity_counter);
+    GST_DEBUG ("CONTINUITY: Initialize to %d", cc);
+  } else if ((cc == stream->continuity_counter + 1 ||
+          (stream->continuity_counter == MAX_CONTINUITY && cc == 0))) {
+    GST_LOG ("CONTINUITY: Got expected %d", cc);
   } else {
     GST_ERROR ("CONTINUITY: Mismatch packet %d, stream %d",
-        packet->continuity_counter, stream->continuity_counter);
+        cc, stream->continuity_counter);
     stream->state = PENDING_PACKET_DISCONT;
   }
-  stream->continuity_counter = packet->continuity_counter;
+  stream->continuity_counter = cc;
 
   if (stream->state == PENDING_PACKET_EMPTY) {
     if (G_UNLIKELY (!packet->payload_unit_start_indicator)) {
@@ -1544,22 +1545,21 @@ beach:
 
 static GstFlowReturn
 gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream,
-    MpegTSPacketizerPacket * packet, MpegTSPacketizerSection * section)
+    MpegTSPacketizerPacket * packet, GstMpegTSSection * section)
 {
   GstFlowReturn res = GST_FLOW_OK;
 
   GST_LOG ("pid 0x%04x pusi:%d, afc:%d, cont:%d, payload:%p", packet->pid,
-      packet->payload_unit_start_indicator, packet->adaptation_field_control,
-      packet->continuity_counter, packet->payload);
+      packet->payload_unit_start_indicator, packet->scram_afc_cc & 0x30,
+      FLAGS_CONTINUITY_COUNTER (packet->scram_afc_cc), packet->payload);
 
   if (section) {
-    GST_LOG ("section complete:%d, buffer size %d",
-        section->complete, section->section_length);
+    GST_LOG ("Got section, returning");
     return res;
   }
 
   if (G_UNLIKELY (packet->payload_unit_start_indicator) &&
-      packet->adaptation_field_control & 0x10)
+      FLAGS_HAS_PAYLOAD (packet->scram_afc_cc))
     /* Flush previous data */
     res = gst_ts_demux_push_pending_data (demux, stream);
 
@@ -1598,7 +1598,7 @@ gst_ts_demux_flush (MpegTSBase * base, gboolean hard)
 
 static GstFlowReturn
 gst_ts_demux_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
-    MpegTSPacketizerSection * section)
+    GstMpegTSSection * section)
 {
   GstTSDemux *demux = GST_TS_DEMUX_CAST (base);
   TSDemuxStream *stream = NULL;