]> git.sesse.net Git - vlc/blobdiff - modules/demux/mpeg/ts.c
. in PMT decoder, fix the iso639-2B language code decoding bug:
[vlc] / modules / demux / mpeg / ts.c
index 3b146e6f47099f61bdf7c173374f81b3cc462ece..df434a99fd6f250978d7d4c8465e3a89d5a31f18 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_ts.c : Transport Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: ts.c,v 1.20 2003/03/18 23:59:07 massiot Exp $
+ * $Id: ts.c,v 1.38 2003/10/27 13:35:15 nitrox Exp $
  *
  * Authors: Henri Fallon <henri@via.ecp.fr>
  *          Johan Bilien <jobi@via.ecp.fr>
  * Preamble
  *****************************************************************************/
 #include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_STDINT_H
-#   include <stdint.h>                                            /* uint8_t */
-#endif
-
 #include <vlc/vlc.h>
 #include <vlc/input.h>
 
@@ -94,13 +88,13 @@ static void TS_DVBPSI_HandlePMT ( input_thread_t *, dvbpsi_pmt_t * );
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
-#define VLS_BACKWARDS_COMPAT_TEXT N_("compatibility with pre-0.4 VLS")
+#define VLS_BACKWARDS_COMPAT_TEXT N_("Compatibility with pre-0.4 VLS")
 #define VLS_BACKWARDS_COMPAT_LONGTEXT N_( \
     "The protocol for transmitting A/52 audio streams changed between VLC " \
     "0.3.x and 0.4. By default VLC assumes you have the latest VLS. In case " \
     "you're using an old version, select this option.")
 
-#define BUGGY_PSI_TEXT N_("buggy PSI")
+#define BUGGY_PSI_TEXT N_("Buggy PSI")
 #define BUGGY_PSI_LONGTEXT N_( \
     "If you have a stream whose PSI packets do not feature incremented " \
     "continuity counters, select this option.")
@@ -136,13 +130,19 @@ static int Activate( vlc_object_t * p_this )
 
     /* Set the demux function */
     p_input->pf_demux = Demux;
+    p_input->pf_demux_control = demux_vaControlDefault;
 
+#if 0
+    /* XXX Unused already done by src/input.c */
     /* Initialize access plug-in structures. */
     if( p_input->i_mtu == 0 )
     {
         /* Improve speed. */
+        msg_Dbg( p_input, "using default mtu (%d) with bufsize (%d)\n",
+                 p_input->i_mtu, INPUT_DEFAULT_BUFSIZE );
         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
     }
+#endif
 
     /* Have a peep at the show. */
     if( input_Peek( p_input, &p_peek, 1 ) < 1 )
@@ -216,8 +216,9 @@ static int Activate( vlc_object_t * p_this )
     /* We'll have to catch the PAT in order to continue
      * Then the input will catch the PMT and then the others ES
      * The PAT es is indepedent of any program. */
-    p_pat_es = input_AddES( p_input, NULL,
-                            0x00, sizeof( es_ts_data_t ) );
+    p_pat_es = input_AddES( p_input, NULL, 0x00,
+                            UNKNOWN_ES, NULL, sizeof( es_ts_data_t ) );
+    p_pat_es->i_fourcc = VLC_FOURCC( 'p', 'a', 't', ' ' );
     p_demux_data = (es_ts_data_t *)p_pat_es->p_demux_data;
     p_demux_data->b_psi = 1;
     p_demux_data->i_psi_type = PSI_IS_PAT;
@@ -297,11 +298,11 @@ static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
     {
         /* unit_start set to 1 -> presence of a pointer field
          * (see ISO/IEC 13818 (2.4.4.2) which should be set to 0x00 */
-        if( (u8)p[0] != 0x00 )
+        if( (uint8_t)p[0] != 0x00 )
         {
             msg_Warn( p_input,
                       "non-zero pointer field found, trying to continue" );
-            p+=(u8)p[0];
+            p+=(uint8_t)p[0];
         }
         else
         {
@@ -310,7 +311,7 @@ static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
 
         /* This is the begining of a new section */
 
-        if( ((u8)(p[1]) & 0xc0) != 0x80 )
+        if( ((uint8_t)(p[1]) & 0xc0) != 0x80 )
         {
             msg_Warn( p_input, "invalid PSI packet" );
             p_psi->b_trash = 1;
@@ -320,7 +321,7 @@ static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
             p_psi->i_section_length = ((p[1] & 0xF) << 8) | p[2];
             p_psi->b_section_complete = 0;
             p_psi->i_read_in_section = 0;
-            p_psi->i_section_number = (u8)p[6];
+            p_psi->i_section_number = (uint8_t)p[6];
 
             if( p_psi->b_is_complete || p_psi->i_section_number == 0 )
             {
@@ -328,7 +329,7 @@ static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
                 p_psi->b_is_complete = 0;
                 p_psi->b_trash = 0;
                 p_psi->i_version_number = ( p[5] >> 1 ) & 0x1f;
-                p_psi->i_last_section_number = (u8)p[7];
+                p_psi->i_last_section_number = (uint8_t)p[7];
 
                 /* We'll write at the begining of the buffer */
                 p_psi->p_current = p_psi->buffer;
@@ -346,7 +347,7 @@ static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
                                   "PSI version differs inside same PAT" );
                         p_psi->b_trash = 1;
                     }
-                    if( p_psi->i_section_number + 1 != (u8)p[6] )
+                    if( p_psi->i_section_number + 1 != (uint8_t)p[6] )
                     {
                         msg_Warn( p_input,
                                   "PSI Section discontinuity, packet lost?" );
@@ -445,17 +446,17 @@ static void TSDecodePAT( input_thread_t * p_input, es_descriptor_t * p_es )
 
         do
         {
-            i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
+            i_section_length = ((uint32_t)(p_current_data[1] & 0xF) << 8) |
                                  p_current_data[2];
-            i_current_section = (u8)p_current_data[6];
+            i_current_section = (uint8_t)p_current_data[6];
 
             for( i_loop = 0;
                  ( i_loop < (i_section_length - 9) / 4 ) && !b_changed;
                  i_loop++ )
             {
-                i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
+                i_program_id = ( (uint32_t)*(p_current_data + i_loop * 4 + 8) << 8 )
                                  | *(p_current_data + i_loop * 4 + 9);
-                i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
+                i_pmt_pid = ( ((uint32_t)*(p_current_data + i_loop * 4 + 10) & 0x1F)
                                     << 8 )
                                | *(p_current_data + i_loop * 4 + 11);
 
@@ -507,15 +508,15 @@ static void TSDecodePAT( input_thread_t * p_input, es_descriptor_t * p_es )
 
         do
         {
-            i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
+            i_section_length = ((uint32_t)(p_current_data[1] & 0xF) << 8) |
                                  p_current_data[2];
-            i_current_section = (u8)p_current_data[6];
+            i_current_section = (uint8_t)p_current_data[6];
 
             for( i_loop = 0; i_loop < (i_section_length - 9) / 4 ; i_loop++ )
             {
-                i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
+                i_program_id = ( (uint32_t)*(p_current_data + i_loop * 4 + 8) << 8 )
                                  | *(p_current_data + i_loop * 4 + 9);
-                i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
+                i_pmt_pid = ( ((uint32_t)*(p_current_data + i_loop * 4 + 10) & 0x1F)
                                     << 8 )
                                | *(p_current_data + i_loop * 4 + 11);
 
@@ -531,8 +532,9 @@ static void TSDecodePAT( input_thread_t * p_input, es_descriptor_t * p_es )
                     p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
 
                     /* Add the PMT ES to this program */
-                    p_current_es = input_AddES( p_input, p_pgrm,(u16)i_pmt_pid,
-                                        sizeof( es_ts_data_t) );
+                    p_current_es = input_AddES( p_input, p_pgrm,(uint16_t)i_pmt_pid,
+                        UNKNOWN_ES, NULL, sizeof( es_ts_data_t) );
+                    p_current_es->i_fourcc = VLC_FOURCC( 'p', 'm', 't', ' ' );
                     p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
                     p_es_demux->b_psi = 1;
                     p_es_demux->i_psi_type = PSI_IS_PMT;
@@ -587,7 +589,7 @@ static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
         p_current_section = p_psi->buffer;
         p_current_data = p_psi->buffer;
 
-        p_pgrm_data->i_pcr_pid = ( ((u32)*(p_current_section + 8) & 0x1F) << 8 ) |
+        p_pgrm_data->i_pcr_pid = ( ((uint32_t)*(p_current_section + 8) & 0x1F) << 8 ) |
                                     *(p_current_section + 9);
 
 
@@ -610,10 +612,10 @@ static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
         /* Then add what we received in this PMT */
         do
         {
-            i_section_length = ( ((u32)*(p_current_data + 1) & 0xF) << 8 ) |
+            i_section_length = ( ((uint32_t)*(p_current_data + 1) & 0xF) << 8 ) |
                                   *(p_current_data + 2);
-            i_current_section = (u8)p_current_data[6];
-            i_prog_info_length = ( ((u32)*(p_current_data + 10) & 0xF) << 8 ) |
+            i_current_section = (uint8_t)p_current_data[6];
+            i_prog_info_length = ( ((uint32_t)*(p_current_data + 10) & 0xF) << 8 ) |
                                     *(p_current_data + 11);
 
             /* For the moment we ignore program descriptors */
@@ -624,19 +626,16 @@ static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
             while( p_current_data < p_current_section + i_section_length -1 )
             {
                 i_stream_type = (int)p_current_data[0];
-                i_pid = ( ((u32)*(p_current_data + 1) & 0x1F) << 8 ) |
+                i_pid = ( ((uint32_t)*(p_current_data + 1) & 0x1F) << 8 ) |
                            *(p_current_data + 2);
-                i_es_info_length = ( ((u32)*(p_current_data + 3) & 0xF) << 8 ) |
+                i_es_info_length = ( ((uint32_t)*(p_current_data + 3) & 0xF) << 8 ) |
                                       *(p_current_data + 4);
 
-                /* Add this ES to the program */
-                p_new_es = input_AddES( p_input, p_es->p_pgrm,
-                                        (u16)i_pid, sizeof( es_ts_data_t ) );
-                ((es_ts_data_t *)p_new_es->p_demux_data)->i_continuity_counter = 0xFF;
-
                 /* Tell the interface what kind of stream it is and select
                  * the required ones */
                 {
+                    int i_fourcc, i_cat, i_stream_id;
+
                     switch( i_stream_type )
                     {
                         case MPEG1_VIDEO_ES:
@@ -644,72 +643,82 @@ static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
                         case MPEG2_MOTO_VIDEO_ES:
                             /* This isn't real, but we don't actually use
                              * it. */
-                            p_new_es->i_stream_id = 0xE0;
-                            p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
-                            p_new_es->i_cat = VIDEO_ES;
+                            i_stream_id = 0xE0;
+                            i_fourcc = VLC_FOURCC('m','p','g','v');
+                            i_cat = VIDEO_ES;
                             break;
                         case MPEG1_AUDIO_ES:
                         case MPEG2_AUDIO_ES:
                             /* This isn't real, but we don't actually use
                              * it. */
-                            p_new_es->i_stream_id = 0xC0;
-                            p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
-                            p_new_es->i_cat = AUDIO_ES;
+                            i_stream_id = 0xC0;
+                            i_fourcc = VLC_FOURCC('m','p','g','a');
+                            i_cat = AUDIO_ES;
                             break;
                         case A52_AUDIO_ES:
-                        case A52DVB_AUDIO_ES:
                             if ( !b_vls_compat )
-                                p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
+                                i_fourcc = VLC_FOURCC('a','5','2',' ');
                             else
-                                p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = AUDIO_ES;
+                                i_fourcc = VLC_FOURCC('a','5','2','b');
+                            i_stream_id = 0xBD;
+                            i_cat = AUDIO_ES;
                             break;
                         case LPCM_AUDIO_ES:
-                            p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = AUDIO_ES;
+                            i_fourcc = VLC_FOURCC('l','p','c','m');
+                            i_stream_id = 0xBD;
+                            i_cat = AUDIO_ES;
                             break;
                         case DVD_SPU_ES:
                             if ( !b_vls_compat )
-                                p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
+                                i_fourcc = VLC_FOURCC('s','p','u',' ');
                             else
-                                p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = SPU_ES;
+                                i_fourcc = VLC_FOURCC('s','p','u','b');
+                            i_stream_id = 0xBD;
+                            i_cat = SPU_ES;
                             break;
                         case SDDS_AUDIO_ES:
-                            p_new_es->i_fourcc = VLC_FOURCC('s','d','d','s');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = AUDIO_ES;
+                            i_fourcc = VLC_FOURCC('s','d','d','s');
+                            i_stream_id = 0xBD;
+                            i_cat = AUDIO_ES;
                             break;
                         case DTS_AUDIO_ES:
-                            p_new_es->i_fourcc = VLC_FOURCC('d','t','s',' ');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = AUDIO_ES;
+                            i_fourcc = VLC_FOURCC('d','t','s',' ');
+                            i_stream_id = 0xBD;
+                            i_cat = AUDIO_ES;
                             break;
                         /* 'b' stands for 'buggy' */
                         case A52B_AUDIO_ES:
-                            p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = AUDIO_ES;
+                            i_fourcc = VLC_FOURCC('a','5','2','b');
+                            i_stream_id = 0xBD;
+                            i_cat = AUDIO_ES;
                             break;
                         case LPCMB_AUDIO_ES:
-                            p_new_es->i_fourcc = VLC_FOURCC('l','p','c','b');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = AUDIO_ES;
+                            i_fourcc = VLC_FOURCC('l','p','c','b');
+                            i_stream_id = 0xBD;
+                            i_cat = AUDIO_ES;
                             break;
                         case DVDB_SPU_ES:
-                            p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
-                            p_new_es->i_stream_id = 0xBD;
-                            p_new_es->i_cat = SPU_ES;
+                            i_fourcc = VLC_FOURCC('s','p','u','b');
+                            i_stream_id = 0xBD;
+                            i_cat = SPU_ES;
                             break;
 
                         default :
-                            p_new_es->i_fourcc = 0;
-                            p_new_es->i_cat = UNKNOWN_ES;
+                            i_stream_id = 0;
+                            i_fourcc = 0;
+                            i_cat = UNKNOWN_ES;
                             break;
                     }
+
+                    /* Add this ES to the program */
+                    p_new_es = input_AddES( p_input, p_es->p_pgrm, (uint16_t)i_pid,
+                                   i_cat, NULL, sizeof( es_ts_data_t ) );
+
+                    ((es_ts_data_t *)p_new_es->p_demux_data)->i_continuity_counter = 0xFF;
+
+                    p_new_es->i_stream_id = i_stream_id;
+                    p_new_es->i_fourcc = i_fourcc;
+
                 }
 
                 p_current_data += 5 + i_es_info_length;
@@ -728,7 +737,7 @@ static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
         if( !p_input->stream.p_selected_program )
         {
             pgrm_descriptor_t *     p_pgrm_to_select;
-            u16 i_id = (u16)config_GetInt( p_input, "program" );
+            uint16_t i_id = (uint16_t)config_GetInt( p_input, "program" );
 
             if( i_id != 0 ) /* if user specified a program */
             {
@@ -1166,9 +1175,12 @@ static void TS_DVBPSI_HandlePAT( input_thread_t * p_input,
 
     p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
 
-    if ( ( p_new_pat->b_current_next && ( p_new_pat->i_version != p_stream_data->i_pat_version ) ) ||
-            p_stream_data->i_pat_version == PAT_UNINITIALIZED  )
+    if( ( p_new_pat->b_current_next &&
+          ( p_new_pat->i_version != p_stream_data->i_pat_version ) ) ||
+        p_stream_data->i_pat_version == PAT_UNINITIALIZED  )
     {
+        msg_Dbg( p_input, "Processing PAT version %d", p_new_pat->i_version );
+
         /* Delete all programs */
         while( p_input->stream.i_pgrm_number )
         {
@@ -1180,6 +1192,10 @@ static void TS_DVBPSI_HandlePAT( input_thread_t * p_input,
                 MP4_IODClean( &p_pgrm_demux_old->iod );
             }
 
+            /* Delete old PMT decoder */
+            if( p_pgrm_demux_old->p_pmt_handle )
+                dvbpsi_DetachPMT( p_pgrm_demux_old->p_pmt_handle );
+
             input_DelProgram( p_input, p_input->stream.pp_programs[0] );
         }
 
@@ -1188,6 +1204,8 @@ static void TS_DVBPSI_HandlePAT( input_thread_t * p_input,
 
         while( p_pgrm )
         {
+            msg_Dbg( p_input, "New program: %d", p_pgrm->i_number );
+
             /* If program = 0, we're having info about NIT not PMT */
             if( p_pgrm->i_number )
             {
@@ -1200,21 +1218,13 @@ static void TS_DVBPSI_HandlePAT( input_thread_t * p_input,
 
                 /* Add the PMT ES to this program */
                 p_current_es = input_AddES( p_input, p_new_pgrm,
-                                            (u16) p_pgrm->i_pid,
-                                            sizeof( es_ts_data_t) );
+                                            (uint16_t)p_pgrm->i_pid, UNKNOWN_ES,
+                                            NULL, sizeof(es_ts_data_t) );
+                p_current_es->i_fourcc = VLC_FOURCC( 'p', 'm', 't', ' ' );
                 p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
                 p_es_demux->b_psi = 1;
                 p_es_demux->i_psi_type = PSI_IS_PMT;
-
-                p_es_demux->p_psi_section = malloc( sizeof( psi_section_t ) );
-                if ( p_es_demux->p_psi_section == NULL )
-                {
-                    msg_Err( p_input, "out of memory" );
-                    p_input->b_error = 1;
-                    return;
-                }
-
-                p_es_demux->p_psi_section->b_is_complete = 0;
+                p_es_demux->p_psi_section = NULL;
                 p_es_demux->i_continuity_counter = 0xFF;
 
                 /* Create a PMT decoder */
@@ -1265,10 +1275,31 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
     p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
     p_pgrm_demux->i_pcr_pid = p_new_pmt->i_pcr_pid;
 
-    if( ( p_new_pmt->b_current_next && ( p_new_pmt->i_version != p_pgrm_demux->i_pmt_version ) ) ||
-            p_pgrm_demux->i_pmt_version == PMT_UNINITIALIZED )
+    if( ( p_new_pmt->b_current_next &&
+          ( p_new_pmt->i_version != p_pgrm_demux->i_pmt_version ) ) ||
+          p_pgrm_demux->i_pmt_version == PMT_UNINITIALIZED )
     {
         dvbpsi_descriptor_t *p_dr = p_new_pmt->p_first_descriptor;
+        int i_loop;
+
+        msg_Dbg( p_input, "Processing PMT for program %d version %d",
+                 p_new_pmt->i_program_number, p_new_pmt->i_version );
+
+        /* Delete all ES in this program  except the PSI. We start from the
+         * end because i_es_number gets decremented after each deletion. */
+        for( i_loop = p_pgrm->i_es_number ; i_loop > 0 ; )
+        {
+            es_ts_data_t *              p_es_demux;
+
+            i_loop--;
+            p_es_demux = (es_ts_data_t *)
+                         p_pgrm->pp_es[i_loop]->p_demux_data;
+            if ( !p_es_demux->b_psi )
+            {
+                input_DelES( p_input, p_pgrm->pp_es[i_loop] );
+            }
+        }
+
         /* IOD */
         while( p_dr && ( p_dr->i_tag != 0x1d ) )
             p_dr = p_dr->p_next;
@@ -1281,245 +1312,240 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
         p_es = p_new_pmt->p_first_es;
         while( p_es )
         {
-            /* Add this ES */
-            p_new_es = input_AddES( p_input, p_pgrm,
-                            (u16)p_es->i_pid, sizeof( es_ts_data_t ) );
-            if( p_new_es == NULL )
-            {
-                msg_Err( p_input, "could not add ES %d", p_es->i_pid );
-                p_input->b_error = 1;
-                return;
-            }
-            ((es_ts_data_t *)p_new_es->p_demux_data)->i_continuity_counter = 0xFF;
+            vlc_fourcc_t i_fourcc;
+            int i_size, i_cat, i_stream_id = 0;
+            es_ts_data_t demux_data;
+            BITMAPINFOHEADER *p_bih = NULL;
+            WAVEFORMATEX *p_wf = NULL;
+            char psz_desc[30];
+
+            memset( &demux_data, 0, sizeof(es_ts_data_t) );
+            *psz_desc = 0;
 
             switch( p_es->i_type )
             {
                 case MPEG1_VIDEO_ES:
                 case MPEG2_VIDEO_ES:
                 case MPEG2_MOTO_VIDEO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
-                    p_new_es->i_cat = VIDEO_ES;
+                    i_fourcc = VLC_FOURCC('m','p','g','v');
+                    i_cat = VIDEO_ES;
                     break;
                 case MPEG1_AUDIO_ES:
                 case MPEG2_AUDIO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
-                    p_new_es->i_cat = AUDIO_ES;
+                    i_fourcc = VLC_FOURCC('m','p','g','a');
+                    i_cat = AUDIO_ES;
                     break;
                 case A52_AUDIO_ES:
-                case A52DVB_AUDIO_ES:
                     if ( !b_vls_compat )
-                        p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
+                        i_fourcc = VLC_FOURCC('a','5','2',' ');
                     else
-                        p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
-                    p_new_es->i_cat = AUDIO_ES;
-                    p_new_es->i_stream_id = 0xBD;
+                        i_fourcc = VLC_FOURCC('a','5','2','b');
+                    i_cat = AUDIO_ES;
+                    i_stream_id = 0xBD;
                     break;
                 case DVD_SPU_ES:
                     if ( !b_vls_compat )
-                        p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
+                        i_fourcc = VLC_FOURCC('s','p','u',' ');
                     else
-                        p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
-                    p_new_es->i_cat = SPU_ES;
-                    p_new_es->i_stream_id = 0xBD;
+                        i_fourcc = VLC_FOURCC('s','p','u','b');
+                    i_cat = SPU_ES;
+                    i_stream_id = 0xBD;
                     break;
                 case LPCM_AUDIO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
-                    p_new_es->i_cat = AUDIO_ES;
-                    p_new_es->i_stream_id = 0xBD;
+                    i_fourcc = VLC_FOURCC('l','p','c','m');
+                    i_cat = AUDIO_ES;
+                    i_stream_id = 0xBD;
                     break;
                 case SDDS_AUDIO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('s','d','d','s');
-                    p_new_es->i_stream_id = 0xBD;
-                    p_new_es->i_cat = AUDIO_ES;
+                    i_fourcc = VLC_FOURCC('s','d','d','s');
+                    i_stream_id = 0xBD;
+                    i_cat = AUDIO_ES;
                     break;
                 case DTS_AUDIO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('d','t','s',' ');
-                    p_new_es->i_stream_id = 0xBD;
-                    p_new_es->i_cat = AUDIO_ES;
+                    i_fourcc = VLC_FOURCC('d','t','s',' ');
+                    i_stream_id = 0xBD;
+                    i_cat = AUDIO_ES;
                     break;
                 case A52B_AUDIO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
-                    p_new_es->i_cat = AUDIO_ES;
-                    p_new_es->i_stream_id = 0xBD;
+                    i_fourcc = VLC_FOURCC('a','5','2','b');
+                    i_cat = AUDIO_ES;
+                    i_stream_id = 0xBD;
                     break;
                 case DVDB_SPU_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
-                    p_new_es->i_cat = SPU_ES;
-                    p_new_es->i_stream_id = 0xBD;
+                    i_fourcc = VLC_FOURCC('s','p','u','b');
+                    i_cat = SPU_ES;
+                    i_stream_id = 0xBD;
                     break;
                 case LPCMB_AUDIO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('l','p','c','b');
-                    p_new_es->i_cat = AUDIO_ES;
-                    p_new_es->i_stream_id = 0xBD;
+                    i_fourcc = VLC_FOURCC('l','p','c','b');
+                    i_cat = AUDIO_ES;
+                    i_stream_id = 0xBD;
                     break;
                 case MPEG4_VIDEO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('m','p','4','v');
-                    p_new_es->i_cat = VIDEO_ES;
-                    p_new_es->i_stream_id = 0xfa;
+                    i_fourcc = VLC_FOURCC('m','p','4','v');
+                    i_cat = VIDEO_ES;
+                    i_stream_id = 0xfa;
                     break;
                 case MPEG4_AUDIO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC('m','p','4','a');
-                    p_new_es->i_cat = AUDIO_ES;
-                    p_new_es->i_stream_id = 0xfa;
+                    i_fourcc = VLC_FOURCC('m','p','4','a');
+                    i_cat = AUDIO_ES;
+                    i_stream_id = 0xfa;
                     break;
                 case MSCODEC_VIDEO_ES:
-                    p_new_es->i_fourcc = VLC_FOURCC(0,0,0,0);   // fixed later
-                    p_new_es->i_cat = VIDEO_ES;
-                    p_new_es->i_stream_id = 0xa0;
+                    i_fourcc = VLC_FOURCC(0,0,0,0);   /* fixed later */
+                    i_cat = VIDEO_ES;
+                    i_stream_id = 0xa0;
+                    break;
+                case PES_PRIVATE_ES:
+                    /* We need to check a descriptor to find the real codec */
+                    i_fourcc = VLC_FOURCC(0,0,0,0);   /* fixed later */
+                    i_cat = UNKNOWN_ES;
+                    i_stream_id = 0xbd;
                     break;
                 default:
-                    p_new_es->i_fourcc = 0;
-                    p_new_es->i_cat = UNKNOWN_ES;
+                    i_fourcc = 0;
+                    i_cat = UNKNOWN_ES;
+                    i_stream_id = 0;
             }
 
-            if( p_es->i_type == MPEG4_VIDEO_ES || p_es->i_type == MPEG4_AUDIO_ES )
+            if( p_es->i_type == MPEG4_VIDEO_ES ||
+                p_es->i_type == MPEG4_AUDIO_ES )
             {
                 /* mpeg4 stream, search sl_descriptor */
                 dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
-                es_ts_data_t        *p_es_demux =
-                                        (es_ts_data_t*)p_new_es->p_demux_data;
 
-                while( p_dr && ( p_dr->i_tag != 0x1f ) )
-                    p_dr = p_dr->p_next;
+                while( p_dr && ( p_dr->i_tag != 0x1f ) ) p_dr = p_dr->p_next;
+
                 if( p_dr && p_dr->i_length == 2 )
                 {
                     int i_es_descr_index;
 
-                    p_es_demux->i_es_id =
+                    demux_data.i_es_id =
                         ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1];
-                    p_es_demux->p_es_descr = NULL;
+                    demux_data.p_es_descr = NULL;
 
                     msg_Warn( p_input, "found SL_descriptor" );
-                    for( i_es_descr_index = 0; i_es_descr_index < 255; i_es_descr_index++ )
+                    for( i_es_descr_index = 0; i_es_descr_index < 255;
+                         i_es_descr_index++ )
                     {
                         if( p_pgrm_demux->iod.es_descr[i_es_descr_index].b_ok &&
-                            p_pgrm_demux->iod.es_descr[i_es_descr_index].i_es_id == p_es_demux->i_es_id )
+                            p_pgrm_demux->iod.es_descr[i_es_descr_index].i_es_id == demux_data.i_es_id )
                         {
-                            p_es_demux->p_es_descr = &p_pgrm_demux->iod.es_descr[i_es_descr_index];
+                            demux_data.p_es_descr =
+                                &p_pgrm_demux->iod.es_descr[i_es_descr_index];
                             break;
                         }
                     }
                 }
-                if( p_es_demux->p_es_descr != NULL )
+
+                if( demux_data.p_es_descr != NULL )
                 {
-                    vlc_fourcc_t i_fourcc;
-                    int          i_cat;
-                    p_es_demux->b_mpeg4 = 1;
+#define DESCR demux_data.p_es_descr->dec_descr
+                    demux_data.b_mpeg4 = 1;
 
                     /* fix fourcc */
-                    switch( p_es_demux->p_es_descr->dec_descr.i_streamType )
+                    switch( DESCR.i_streamType )
                     {
-                        case 0x04:  /* VisualStream */
-                            i_cat = VIDEO_ES;
-                            switch( p_es_demux->p_es_descr->dec_descr.i_objectTypeIndication )
-                            {
-                                case 0x20:
-                                    i_fourcc = VLC_FOURCC('m','p','4','v');     // mpeg4
-                                    break;
-                                case 0x60:
-                                case 0x61:
-                                case 0x62:
-                                case 0x63:
-                                case 0x64:
-                                case 0x65:
-                                    i_fourcc = VLC_FOURCC( 'm','p','g','v' );   // mpeg2
-                                    break;
-                                case 0x6a:
-                                    i_fourcc = VLC_FOURCC( 'm','p','g','v' );   // mpeg1
-                                    break;
-                                case 0x6c:
-                                    i_fourcc = VLC_FOURCC( 'j','p','e','g' );   // mpeg1
-                                    break;
-                                default:
-                                    i_fourcc = 0;
-                                    break;
-                            }
+                    case 0x04:  /* VisualStream */
+                        i_cat = VIDEO_ES;
+                        switch( DESCR.i_objectTypeIndication )
+                        {
+                        case 0x20:
+                            i_fourcc = VLC_FOURCC('m','p','4','v');    // mpeg4
                             break;
-                        case 0x05:  /* AudioStream */
-                            i_cat = AUDIO_ES;
-                            switch( p_es_demux->p_es_descr->dec_descr.i_objectTypeIndication )
-                            {
-                                case 0x40:
-                                    i_fourcc = VLC_FOURCC('m','p','4','a');     // mpeg4
-                                    break;
-                                case 0x66:
-                                case 0x67:
-                                case 0x68:
-                                    i_fourcc = VLC_FOURCC('m','p','4','a');     // mpeg2 aac
-                                    break;
-                                case 0x69:
-                                    i_fourcc = VLC_FOURCC('m','p','g','a');     // mpeg2
-                                    break;
-                                case 0x6b:
-                                    i_fourcc = VLC_FOURCC('m','p','g','a');     // mpeg1
-                                    break;
-                                default:
-                                    i_fourcc = 0;
-                                    break;
-                            }
+                        case 0x60:
+                        case 0x61:
+                        case 0x62:
+                        case 0x63:
+                        case 0x64:
+                        case 0x65:
+                            i_fourcc = VLC_FOURCC( 'm','p','g','v' );  // mpeg2
+                            break;
+                        case 0x6a:
+                            i_fourcc = VLC_FOURCC( 'm','p','g','v' );  // mpeg1
+                            break;
+                        case 0x6c:
+                            i_fourcc = VLC_FOURCC( 'j','p','e','g' );  // mpeg1
                             break;
                         default:
-                            i_cat = UNKNOWN_ES;
                             i_fourcc = 0;
                             break;
-                    }
-
-                    p_new_es->i_fourcc = i_fourcc;
-                    p_new_es->i_cat    = i_cat;
-                    switch( i_cat )
-                    {
-                        case VIDEO_ES:
-                            {
-                                int i_size;
-                                BITMAPINFOHEADER *p_bih;
-
-                                i_size = sizeof( BITMAPINFOHEADER ) +
-                                                 p_es_demux->p_es_descr->dec_descr.i_decoder_specific_info_len;
-                                p_new_es->p_bitmapinfoheader = (void*)p_bih = malloc( i_size );
-                                p_bih->biSize = i_size;
-                                p_bih->biWidth = 0;
-                                p_bih->biHeight = 0;
-                                p_bih->biPlanes = 1;
-                                p_bih->biBitCount = 0;
-                                p_bih->biCompression = 0;
-                                p_bih->biSizeImage = 0;
-                                p_bih->biXPelsPerMeter = 0;
-                                p_bih->biYPelsPerMeter = 0;
-                                p_bih->biClrUsed = 0;
-                                p_bih->biClrImportant = 0;
-                                memcpy( &p_bih[1],
-                                        p_es_demux->p_es_descr->dec_descr.p_decoder_specific_info,
-                                        p_es_demux->p_es_descr->dec_descr.i_decoder_specific_info_len );
-                            }
+                        }
+                        break;
+                    case 0x05:  /* AudioStream */
+                        i_cat = AUDIO_ES;
+                        switch( DESCR.i_objectTypeIndication )
+                        {
+                        case 0x40:
+                            i_fourcc = VLC_FOURCC('m','p','4','a');    // mpeg4
                             break;
-                        case AUDIO_ES:
-                            {
-                                int i_size;
-                                WAVEFORMATEX *p_wf;
-
-                                i_size = sizeof( WAVEFORMATEX ) +
-                                                 p_es_demux->p_es_descr->dec_descr.i_decoder_specific_info_len;
-                                p_new_es->p_waveformatex = (void*)p_wf = malloc( i_size );
-                                p_wf->wFormatTag = 0xffff;
-                                p_wf->nChannels = 0;
-                                p_wf->nSamplesPerSec = 0;
-                                p_wf->nAvgBytesPerSec = 0;
-                                p_wf->nBlockAlign = 1;
-                                p_wf->wBitsPerSample = 0;
-                                p_wf->cbSize = p_es_demux->p_es_descr->dec_descr.i_decoder_specific_info_len;
-                                memcpy( &p_wf[1],
-                                        p_es_demux->p_es_descr->dec_descr.p_decoder_specific_info,
-                                        p_es_demux->p_es_descr->dec_descr.i_decoder_specific_info_len );
-                            }
+                        case 0x66:
+                        case 0x67:
+                        case 0x68:
+                            i_fourcc = VLC_FOURCC('m','p','4','a');// mpeg2 aac
+                            break;
+                        case 0x69:
+                            i_fourcc = VLC_FOURCC('m','p','g','a');    // mpeg2
+                            break;
+                        case 0x6b:
+                            i_fourcc = VLC_FOURCC('m','p','g','a');    // mpeg1
                             break;
                         default:
+                            i_fourcc = 0;
                             break;
+                        }
+                        break;
+                    default:
+                        i_cat = UNKNOWN_ES;
+                        i_fourcc = 0;
+                        break;
+                    }
+
+                    switch( i_cat )
+                    {
+                    case VIDEO_ES:
+                        i_size = sizeof( BITMAPINFOHEADER ) +
+                                 DESCR.i_decoder_specific_info_len;
+                        p_bih = malloc( i_size );
+                        p_bih->biSize = i_size;
+                        p_bih->biWidth = 0;
+                        p_bih->biHeight = 0;
+                        p_bih->biPlanes = 1;
+                        p_bih->biBitCount = 0;
+                        p_bih->biCompression = 0;
+                        p_bih->biSizeImage = 0;
+                        p_bih->biXPelsPerMeter = 0;
+                        p_bih->biYPelsPerMeter = 0;
+                        p_bih->biClrUsed = 0;
+                        p_bih->biClrImportant = 0;
+                        memcpy( &p_bih[1],
+                                DESCR.p_decoder_specific_info,
+                                DESCR.i_decoder_specific_info_len );
+                        break;
+                    case AUDIO_ES:
+                        i_size = sizeof( WAVEFORMATEX ) +
+                                 DESCR.i_decoder_specific_info_len;
+                        p_wf = malloc( i_size );
+                        p_wf->wFormatTag = 0xffff;
+                        p_wf->nChannels = 0;
+                        p_wf->nSamplesPerSec = 0;
+                        p_wf->nAvgBytesPerSec = 0;
+                        p_wf->nBlockAlign = 1;
+                        p_wf->wBitsPerSample = 0;
+                        p_wf->cbSize = DESCR.i_decoder_specific_info_len;
+                        memcpy( &p_wf[1],
+                                DESCR.p_decoder_specific_info,
+                                DESCR.i_decoder_specific_info_len );
+                        break;
+                    default:
+                        break;
                     }
                 }
                 else
                 {
-                    msg_Warn( p_input, "mpeg4 stream without (valid) sl_descriptor" );
-                    p_es_demux->b_mpeg4 = 0;
+                    msg_Warn( p_input,
+                              "mpeg4 stream without (valid) sl_descriptor" );
+                    demux_data.b_mpeg4 = 0;
                 }
 
             }
@@ -1527,24 +1553,19 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
             {
                 /* crapy ms codec stream, search private descriptor */
                 dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
-                es_ts_data_t        *p_es_demux =
-                                        (es_ts_data_t*)p_new_es->p_demux_data;
 
-                while( p_dr && ( p_dr->i_tag != 0xa0 ) )
-                    p_dr = p_dr->p_next;
+                while( p_dr && ( p_dr->i_tag != 0xa0 ) ) p_dr = p_dr->p_next;
+
                 if( p_dr && p_dr->i_length >= 8 )
                 {
-                    int i_size;
                     int i_bih_size;
-                    BITMAPINFOHEADER *p_bih;
+                    i_fourcc = VLC_FOURCC( p_dr->p_data[0], p_dr->p_data[1],
+                                           p_dr->p_data[2], p_dr->p_data[3] );
 
-                    p_new_es->i_fourcc = ( p_dr->p_data[0] << 24 )| ( p_dr->p_data[1] << 16 )|
-                                         ( p_dr->p_data[2] <<  8 )| ( p_dr->p_data[3] );
-
-                    i_bih_size = ( ( p_dr->p_data[8] << 8)|( p_dr->p_data[9] ) );
+                    i_bih_size = (p_dr->p_data[8] << 8) | p_dr->p_data[9];
                     i_size = sizeof( BITMAPINFOHEADER ) + i_bih_size;
 
-                    p_new_es->p_bitmapinfoheader = (void*)p_bih = malloc( i_size );
+                    p_bih = malloc( i_size );
                     p_bih->biSize = i_size;
                     p_bih->biWidth = ( p_dr->p_data[4] << 8 )|p_dr->p_data[5];
                     p_bih->biHeight = ( p_dr->p_data[6] << 8 )|p_dr->p_data[7];
@@ -1556,24 +1577,48 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
                     p_bih->biYPelsPerMeter = 0;
                     p_bih->biClrUsed = 0;
                     p_bih->biClrImportant = 0;
-                    memcpy( &p_bih[1],
-                            &p_dr->p_data[10],
-                            i_bih_size );
+                    memcpy( &p_bih[1], &p_dr->p_data[10], i_bih_size );
                 }
                 else
                 {
-                    msg_Warn( p_input, "private ms-codec stream without bih private sl_descriptor" );
-                    p_new_es->i_fourcc = 0;
-                    p_new_es->i_cat = UNKNOWN_ES;
+                    msg_Warn( p_input, "private ms-codec stream without bih "
+                              "private sl_descriptor" );
+                    i_fourcc = 0;
+                    i_cat = UNKNOWN_ES;
                 }
             }
+            else if( p_es->i_type == PES_PRIVATE_ES )
+            {
+                dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
+                /* We have to find a descriptor giving the right codec */
 
-            if(    ( p_new_es->i_cat == AUDIO_ES )
-                || (p_new_es->i_cat == SPU_ES ) )
+                for(p_dr = p_es->p_first_descriptor; p_dr; p_dr = p_dr->p_next)
+                {
+                    if( p_dr->i_tag == 0x6a )
+                    {
+                        /* A52 */
+                        i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
+                        i_cat    = AUDIO_ES;
+                    }
+                    else if( p_dr->i_tag == 0x59 )
+                    {
+                        /* DVB subtitle */
+                        i_fourcc = VLC_FOURCC( 'd', 'v', 'b', 's' );
+                        i_cat    = SPU_ES;
+                    }
+                }
+                if( i_fourcc == VLC_FOURCC(0,0,0,0) )
+                {
+                    msg_Warn( p_input,
+                              "Unknown codec/type for Private PES stream" );
+                }
+            }
+
+            if( i_cat == AUDIO_ES || i_cat == SPU_ES )
             {
                 dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
-                while( p_dr && ( p_dr->i_tag != 0x0a ) )
-                    p_dr = p_dr->p_next;
+                while( p_dr && ( p_dr->i_tag != 0x0a ) ) p_dr = p_dr->p_next;
+
                 if( p_dr )
                 {
                     dvbpsi_iso639_dr_t *p_decoded =
@@ -1582,19 +1627,33 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
                     {
                         const iso639_lang_t * p_iso;
                         p_iso = GetLang_2T((char*)p_decoded->i_iso_639_code);
-                        if(p_iso)
+
+                        if( p_iso && strcmp(p_iso->psz_native_name,"Unknown"))
                         {
-                            if(p_iso->psz_native_name[0])
-                                strcpy( p_new_es->psz_desc,
-                                        p_iso->psz_native_name );
+                            if( p_iso->psz_native_name[0] )
+                                strncpy( psz_desc,
+                                         p_iso->psz_native_name, 20 );
                             else
-                                strcpy( p_new_es->psz_desc,
-                                        p_iso->psz_eng_name );
+                                strncpy( psz_desc,
+                                         p_iso->psz_eng_name, 20 );
                         }
                         else
                         {
-                            strncpy( p_new_es->psz_desc,
-                                     p_decoded->i_iso_639_code, 3 );
+                            p_iso = GetLang_2B(
+                                        (char*)p_decoded->i_iso_639_code);
+                            if ( p_iso )
+                            {
+                              if( p_iso->psz_native_name[0] )
+                                strncpy( psz_desc,
+                                         p_iso->psz_native_name, 20 );
+                              else
+                                strncpy( psz_desc,
+                                         p_iso->psz_eng_name, 20 );
+                            }
+                            else
+                            {
+                              strncpy( psz_desc, p_decoded->i_iso_639_code, 3 );
+                            }
                         }
                     }
                 }
@@ -1602,23 +1661,41 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
                 {
                     case MPEG1_AUDIO_ES:
                     case MPEG2_AUDIO_ES:
-                        strcat( p_new_es->psz_desc, " (mpeg)" );
+                        strcat( psz_desc, " (mpeg)" );
                         break;
                     case LPCM_AUDIO_ES:
                     case LPCMB_AUDIO_ES:
-                        strcat( p_new_es->psz_desc, " (lpcm)" );
+                        strcat( psz_desc, " (lpcm)" );
                         break;
                     case A52_AUDIO_ES:
-                    case A52DVB_AUDIO_ES:
                     case A52B_AUDIO_ES:
-                        strcat( p_new_es->psz_desc, " (A52)" );
+                        strcat( psz_desc, " (A52)" );
                         break;
                     case MPEG4_AUDIO_ES:
-                        strcat( p_new_es->psz_desc, " (aac)" );
+                        strcat( psz_desc, " (aac)" );
                         break;
                 }
             }
 
+            /* Add this ES */
+            p_new_es = input_AddES( p_input, p_pgrm, (uint16_t)p_es->i_pid,
+                                    i_cat, psz_desc, sizeof( es_ts_data_t ) );
+            if( p_new_es == NULL )
+            {
+                msg_Err( p_input, "could not add ES %d", p_es->i_pid );
+                p_input->b_error = 1;
+                return;
+            }
+            p_new_es->i_fourcc = i_fourcc;
+            p_new_es->i_stream_id = i_stream_id;
+            p_new_es->p_bitmapinfoheader = (void*)p_bih;
+            p_new_es->p_waveformatex = (void*)p_wf;
+            memcpy( p_new_es->p_demux_data, &demux_data,
+                    sizeof(es_ts_data_t) );
+
+            ((es_ts_data_t *)p_new_es->p_demux_data)->i_continuity_counter =
+                0xFF;
+
             p_es = p_es->p_next;
         }
 
@@ -1626,7 +1703,7 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
         if( !p_input->stream.p_selected_program )
         {
             pgrm_descriptor_t *     p_pgrm_to_select;
-            u16 i_id = (u16)config_GetInt( p_input, "program" );
+            uint16_t i_id = (uint16_t)config_GetInt( p_input, "program" );
 
             if( i_id != 0 ) /* if user specified a program */
             {
@@ -1636,7 +1713,7 @@ static void TS_DVBPSI_HandlePMT( input_thread_t * p_input,
                     p_input->pf_set_program( p_input, p_pgrm_to_select );
             }
             else
-                    p_input->pf_set_program( p_input, p_pgrm );
+                p_input->pf_set_program( p_input, p_pgrm );
         }
         /* if the pmt belongs to the currently selected program, we
          * reselect it to update its ES */