]> git.sesse.net Git - vlc/blobdiff - modules/demux/mpeg/system.c
* Coding style cleanup: removed tabs and trailing spaces.
[vlc] / modules / demux / mpeg / system.c
index d8088a5c10f238292339ddfc19cbfe15d1962d83..810af40b7f8d89d49e9dae972381094a4f1d4f8a 100644 (file)
@@ -2,19 +2,19 @@
  * system.c: helper module for TS, PS and PES management
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
- * $Id: system.c,v 1.2 2002/08/30 22:22:24 massiot Exp $
+ * $Id: system.c,v 1.26 2003/12/22 14:32:56 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
  *          BenoĆ®t Steiner <benny@via.ecp.fr>
- *          Samuel Hocevar <sam@zoy.org>
+ *          Sam Hocevar <sam@zoy.org>
  *          Henri Fallon <henri@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -29,8 +29,6 @@
  * Preamble
  *****************************************************************************/
 #include <stdlib.h>
-#include <string.h>                                    /* memcpy(), memset() */
-#include <sys/types.h>                                              /* off_t */
 
 #include <vlc/vlc.h>
 #include <vlc/input.h>
@@ -87,10 +85,10 @@ static int Activate ( vlc_object_t *p_this )
 static inline size_t MoveChunk( byte_t * p_dest, data_packet_t ** pp_data_src,
                                 byte_t ** pp_src, size_t i_buf_len )
 {
-    ptrdiff_t           i_available;
+    size_t i_available;
 
-    if( (i_available = (*pp_data_src)->p_payload_end - *pp_src)
-            >= i_buf_len )
+    i_available = (ptrdiff_t)((*pp_data_src)->p_payload_end - *pp_src);
+    if( i_available >= i_buf_len )
     {
         if( p_dest != NULL )
             memcpy( p_dest, *pp_src, i_buf_len );
@@ -99,7 +97,7 @@ static inline size_t MoveChunk( byte_t * p_dest, data_packet_t ** pp_data_src,
     }
     else
     {
-        size_t          i_init_len = i_buf_len;
+        size_t i_init_len = i_buf_len;
 
         do
         {
@@ -114,9 +112,10 @@ static inline size_t MoveChunk( byte_t * p_dest, data_packet_t ** pp_data_src,
                 return( i_init_len - i_buf_len );
             }
             *pp_src = (*pp_data_src)->p_payload_start;
+
+            i_available = (ptrdiff_t)((*pp_data_src)->p_payload_end - *pp_src);
         }
-        while( (i_available = (*pp_data_src)->p_payload_end - *pp_src)
-                <= i_buf_len );
+        while( i_available <= i_buf_len );
 
         if( i_buf_len )
         {
@@ -171,13 +170,13 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
     if( (p_header[0] || p_header[1] || (p_header[2] != 1)) )
     {
         /* packet_start_code_prefix != 0x000001 */
-        msg_Err( p_input, "data loss, PES packet does not start with 000001" );
+        msg_Warn( p_input, "data loss, PES packet does not start with 000001" );
         input_DeletePES( p_input->p_method_data, p_pes );
         p_pes = NULL;
     }
     else
     {
-        int i_pes_header_size, i_payload_size;
+        unsigned int i_pes_header_size, i_payload_size;
 
         if ( p_es->i_pes_real_size &&
              (p_es->i_pes_real_size != p_pes->i_pes_size) )
@@ -187,7 +186,7 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
             msg_Warn( p_input, "packet corrupted, PES sizes do not match" );
         }
 
-        switch( p_es->i_stream_id )
+        switch( p_header[3] )
         {
         case 0xBC:  /* Program stream map */
         case 0xBE:  /* Padding */
@@ -215,7 +214,7 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
                 i_max_len = MoveChunk( p_full_header, &p_data, &p_byte, 12 );
                 if( i_max_len < 2 )
                 {
-                    msg_Warn( p_input, 
+                    msg_Warn( p_input,
                               "PES packet too short to have a MPEG-2 header" );
                     input_DeletePES( p_input->p_method_data,
                                             p_pes );
@@ -290,7 +289,7 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
                 }
                 if( i_pes_header_size == 23 )
                 {
-                    msg_Err( p_input, "too much MPEG-1 stuffing" );
+                    msg_Warn( p_input, "too much MPEG-1 stuffing" );
                     input_DeletePES( p_input->p_method_data, p_pes );
                     p_pes = NULL;
                     return;
@@ -364,17 +363,18 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
         }
 
         /* Welcome to the kludge area ! --Meuuh */
-        if( p_es->i_fourcc == VLC_FOURCC('a','5','2','b') )
+        if ( p_es->i_fourcc == VLC_FOURCC('a','5','2','b')
+              || p_es->i_fourcc == VLC_FOURCC('d','t','s','b') )
         {
-            /* With A/52 audio, we need to skip the first 4 bytes */
+            /* With A/52 or DTS audio, we need to skip the first 4 bytes */
             i_pes_header_size += 4;
         }
-        else if( p_es->i_fourcc == VLC_FOURCC('l','p','c','b')
-                  || p_es->i_fourcc == VLC_FOURCC('s','p','u','b')
-                  || p_es->i_fourcc == VLC_FOURCC('d','t','s','b')
-                  || p_es->i_fourcc == VLC_FOURCC('s','d','d','b') )
+
+        if ( p_es->i_fourcc == VLC_FOURCC('l','p','c','b')
+              || p_es->i_fourcc == VLC_FOURCC('s','p','u','b')
+              || p_es->i_fourcc == VLC_FOURCC('s','d','d','b') )
         {
-            /* With others, we need to skip the first byte */
+            /* stream_private_id */
             i_pes_header_size += 1;
         }
 
@@ -393,7 +393,7 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
             /* Go to the next data packet. */
             if( (p_data = p_data->p_next) == NULL )
             {
-                msg_Err( p_input, "PES header bigger than payload" );
+                msg_Warn( p_input, "PES header bigger than payload" );
                 input_DeletePES( p_input->p_method_data, p_pes );
                 p_pes = NULL;
                 return;
@@ -404,7 +404,7 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
         /* This last packet is partly header, partly payload. */
         if( i_payload_size < i_pes_header_size )
         {
-            msg_Err( p_input, "PES header bigger than payload" );
+            msg_Warn( p_input, "PES header bigger than payload" );
             input_DeletePES( p_input->p_method_data, p_pes );
             p_pes = NULL;
             return;
@@ -414,9 +414,32 @@ static void ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
 
         /* Now we can eventually put the PES packet in the decoder's
          * PES fifo */
-        if( p_es->p_decoder_fifo != NULL )
+        if( p_es->p_dec != NULL )
         {
-            input_DecodePES( p_es->p_decoder_fifo, p_pes );
+            input_DecodePES( p_es->p_dec, p_pes );
+        }
+        else if ( p_es->p_dec == NULL &&
+                   ((es_ts_data_t*)p_es->p_demux_data)->b_dvbsub)
+        {
+            es_descriptor_t* p_dvbsub;
+            uint8_t          i_count;
+            uint8_t         i;
+            i_count = ((es_ts_data_t*)p_es->p_demux_data)->i_dvbsub_es_count;
+
+            // If a language is selected, we send the packet to the decoder
+            for(i = 0; i < i_count; i++)
+            {
+                p_dvbsub = ((es_ts_data_t*)p_es->p_demux_data)->p_dvbsub_es[i];
+                if(p_dvbsub->p_dec !=NULL)
+                {
+                    input_DecodePES ( p_dvbsub->p_dec, p_pes );
+                    break;
+                }
+            }
+            if(i == i_count)
+            {
+                input_DeletePES( p_input->p_method_data, p_pes );
+            }
         }
         else
         {
@@ -441,12 +464,9 @@ static void GatherPES( input_thread_t * p_input, data_packet_t * p_data,
 {
 #define p_pes (p_es->p_pes)
 
-    /* If we lost data, insert a NULL data packet (philosophy : 0 is quite
-     * often an escape sequence in decoders, so that should make them wait
-     * for the next start code). */
-    if( b_packet_lost )
+    if( b_packet_lost && p_pes != NULL )
     {
-        input_NullPacket( p_input, p_es );
+        p_pes->b_discontinuity = 1;
     }
 
     if( b_unit_start && p_pes != NULL )
@@ -479,19 +499,23 @@ static void GatherPES( input_thread_t * p_input, data_packet_t * p_data,
             }
             p_pes->i_rate = p_input->stream.control.i_rate;
             p_pes->p_first = p_data;
-            
+
             /* If the PES header fits in the first data packet, we can
              * already set p_gather->i_pes_real_size. */
             if( p_data->p_payload_end - p_data->p_payload_start
                     >= PES_HEADER_SIZE )
             {
-                p_es->i_pes_real_size = ((u16)p_data->p_payload_start[4] << 8)
-                                         + p_data->p_payload_start[5] + 6;
+                p_es->i_pes_real_size = ((uint16_t)p_data->p_payload_start[4] << 8)
+                                         + p_data->p_payload_start[5];
+                if ( p_es->i_pes_real_size )
+                {
+                    p_es->i_pes_real_size += 6;
+                }
             }
             else
-            { 
+            {
                 p_es->i_pes_real_size = 0;
-            } 
+            }
         }
         else
         {
@@ -505,10 +529,16 @@ static void GatherPES( input_thread_t * p_input, data_packet_t * p_data,
         /* Size of the payload carried in the data packet */
         p_pes->i_pes_size += (p_data->p_payload_end
                                  - p_data->p_payload_start);
-    
+
         /* We can check if the packet is finished */
-        if( p_pes->i_pes_size == p_es->i_pes_real_size )
+        if( p_es->i_pes_real_size  && p_pes->i_pes_size >= p_es->i_pes_real_size )
         {
+            if( p_pes->i_pes_size > p_es->i_pes_real_size )
+            {
+                msg_Warn( p_input,
+                          "Oversized PES packet for PID %d: expected %d, actual %d",
+                          p_es->i_id, p_es->i_pes_real_size, p_pes->i_pes_size );
+            }
             /* The packet is finished, parse it */
             ParsePES( p_input, p_es );
         }
@@ -524,9 +554,9 @@ static void GatherPES( input_thread_t * p_input, data_packet_t * p_data,
 /*****************************************************************************
  * GetID: Get the ID of a stream
  *****************************************************************************/
-static u16 GetID( data_packet_t * p_data )
+static uint16_t GetID( data_packet_t * p_data )
 {
-    u16         i_id;
+    uint16_t i_id;
 
     i_id = p_data->p_demux_start[3];                            /* stream_id */
     if( i_id == 0xBD )
@@ -550,8 +580,8 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
                  (stream_ps_data_t *)p_input->stream.p_demux_data;
     byte_t *            p_byte;
     byte_t *            p_end;
-    int                 i;
-    int                 i_new_es_number = 0;
+    unsigned int        i;
+    unsigned int        i_new_es_number = 0;
 
     if( p_data->p_demux_start + 10 > p_data->p_payload_end )
     {
@@ -595,7 +625,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
     while( p_byte + 4 <= p_end )
     {
         es_descriptor_t *   p_es = NULL;
-        u8                  i_stream_id = p_byte[1];
+        uint8_t             i_stream_id = p_byte[1];
         /* FIXME: there will be a problem with private streams... (same
          * stream_id) */
 
@@ -634,37 +664,43 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
          * so that we can close them more easily at the end. */
         if( p_es == NULL )
         {
-            p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
-                                i_stream_id, 0 );
+            int i_fourcc, i_cat;
+
             switch( p_byte[0] )
             {
             case MPEG1_VIDEO_ES:
             case MPEG2_VIDEO_ES:
-                p_es->i_fourcc = VLC_FOURCC('m','p','g','v');
-                p_es->i_cat = VIDEO_ES;
+            case MPEG2_MOTO_VIDEO_ES:
+                i_fourcc = VLC_FOURCC('m','p','g','v');
+                i_cat = VIDEO_ES;
                 break;
             case DVD_SPU_ES:
-                p_es->i_fourcc = VLC_FOURCC('s','p','u','b');
-                p_es->i_cat = SPU_ES;
+                i_fourcc = VLC_FOURCC('s','p','u','b');
+                i_cat = SPU_ES;
                 break;
             case MPEG1_AUDIO_ES:
             case MPEG2_AUDIO_ES:
-                p_es->i_fourcc = VLC_FOURCC('m','p','g','a');
-                p_es->i_cat = AUDIO_ES;
+                i_fourcc = VLC_FOURCC('m','p','g','a');
+                i_cat = AUDIO_ES;
                 break;
             case A52_AUDIO_ES:
-                p_es->i_fourcc = VLC_FOURCC('a','5','2','b');
-                p_es->i_cat = AUDIO_ES;
+                i_fourcc = VLC_FOURCC('a','5','2','b');
+                i_cat = AUDIO_ES;
                 break;
             case LPCM_AUDIO_ES:
-                p_es->i_fourcc = VLC_FOURCC('l','p','c','b');
-                p_es->i_cat = AUDIO_ES;
+                i_fourcc = VLC_FOURCC('l','p','c','b');
+                i_cat = AUDIO_ES;
                 break;
             default:
-                p_es->i_fourcc = 0;
+                i_cat = UNKNOWN_ES;
+                i_fourcc = 0;
                 break;
             }
 
+            p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
+                                i_stream_id, i_cat, NULL, 0 );
+            p_es->i_fourcc = i_fourcc;
+
             /* input_AddES has inserted the new element at the end. */
             p_input->stream.pp_programs[0]->pp_es[
                 p_input->stream.pp_programs[0]->i_es_number ]
@@ -699,7 +735,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
     {                                                                       \
         return( -1 );                                                       \
     }                                                                       \
-    else if( i_error < SIZE )                                               \
+    else if( (size_t)i_error < SIZE )                                       \
     {                                                                       \
         /* EOF */                                                           \
         return( 0 );                                                        \
@@ -763,6 +799,7 @@ static ssize_t ReadPS( input_thread_t * p_input, data_packet_t ** pp_data )
             else
             {
                 msg_Err( p_input, "unable to determine stream type" );
+                p_input->p_current_data++;
                 return( -1 );
             }
         }
@@ -801,15 +838,15 @@ static ssize_t ReadPS( input_thread_t * p_input, data_packet_t ** pp_data )
 static es_descriptor_t * ParsePS( input_thread_t * p_input,
                                   data_packet_t * p_data )
 {
-    u32                 i_code;
+    uint32_t            i_code;
     es_descriptor_t *   p_es = NULL;
 
     i_code = p_data->p_demux_start[3];
 
     if( i_code > 0xBC ) /* ES start code */
     {
-        u16                 i_id;
-        int                 i_dummy;
+        uint16_t            i_id;
+        unsigned int        i_dummy;
 
         /* This is a PES packet. Find out if we want it or not. */
         i_id = GetID( p_data );
@@ -831,6 +868,7 @@ static es_descriptor_t * ParsePS( input_thread_t * p_input,
         }
         else
         {
+            vlc_bool_t b_auto_spawn = VLC_FALSE;
             stream_ps_data_t * p_demux =
               (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
 
@@ -839,86 +877,130 @@ static es_descriptor_t * ParsePS( input_thread_t * p_input,
 
             if( p_es == NULL && !p_demux->b_has_PSM )
             {
-                p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
-                                    i_id, 0 );
-                if( p_es != NULL )
-                {
-                    p_es->i_stream_id = p_data->p_demux_start[3];
+                int i_fourcc, i_cat;
 
-                    /* Set stream type and auto-spawn. */
-                    if( (i_id & 0xF0) == 0xE0 )
-                    {
-                        /* MPEG video */
-                        p_es->i_fourcc = VLC_FOURCC('m','p','g','v');
-                        p_es->i_cat = VIDEO_ES;
+                /* Set stream type and auto-spawn. */
+                if( (i_id & 0xF0) == 0xE0 )
+                {
+                    /* MPEG video */
+                    i_fourcc = VLC_FOURCC('m','p','g','v');
+                    i_cat = VIDEO_ES;
 #ifdef AUTO_SPAWN
-                        if( !p_input->stream.b_seekable )
-                            input_SelectES( p_input, p_es );
+                    if( !p_input->stream.b_seekable ) b_auto_spawn = VLC_TRUE;
 #endif
-                    }
-                    else if( (i_id & 0xE0) == 0xC0 )
-                    {
-                        /* MPEG audio */
-                        p_es->i_fourcc = VLC_FOURCC('m','p','g','a');
-                        p_es->i_cat = AUDIO_ES;
+                }
+                else if( (i_id & 0xE0) == 0xC0 )
+                {
+                    /* MPEG audio */
+                    i_fourcc = VLC_FOURCC('m','p','g','a');
+                    i_cat = AUDIO_ES;
 #ifdef AUTO_SPAWN
-                        if( !p_input->stream.b_seekable )
-                        if( config_GetInt( p_input, "audio-channel" )
-                                == (p_es->i_id & 0x1F) ||
-                            ( config_GetInt( p_input, "audio-channel" ) < 0
-                              && !(p_es->i_id & 0x1F) ) )
-                        switch( config_GetInt( p_input, "audio-type" ) )
-                        {
-                        case -1:
-                        case REQUESTED_MPEG:
-                            input_SelectES( p_input, p_es );
-                        }
-#endif
-                    }
-                    else if( (i_id & 0xF0FF) == 0x80BD )
+                    if( !p_input->stream.b_seekable )
+                    if( config_GetInt( p_input, "audio-channel" )
+                            == (i_id & 0x1F) ||
+                        ( config_GetInt( p_input, "audio-channel" ) < 0
+                          && !(i_id & 0x1F) ) )
+                    switch( config_GetInt( p_input, "audio-type" ) )
                     {
-                        /* A52 audio (0x80->0x8F) */
-                        p_es->i_fourcc = VLC_FOURCC('a','5','2','b');
-                        p_es->i_cat = AUDIO_ES;
-#ifdef AUTO_SPAWN
-                        if( !p_input->stream.b_seekable )
-                        if( config_GetInt( p_input, "audio-channel" )
-                                == ((p_es->i_id & 0xF00) >> 8) ||
-                            ( config_GetInt( p_input, "audio-channel" ) < 0
-                              && !((p_es->i_id & 0xF00) >> 8)) )
-                        switch( config_GetInt( p_input, "audio-type" ) )
-                        {
-                        case -1:
-                        case REQUESTED_A52:
-                            input_SelectES( p_input, p_es );
-                        }
-#endif
+                    case -1:
+                    case REQUESTED_MPEG:
+                        b_auto_spawn = VLC_TRUE;
                     }
-                    else if( (i_id & 0xE0FF) == 0x20BD )
-                    {
-                        /* Subtitles video (0x20->0x3F) */
-                        p_es->i_fourcc = VLC_FOURCC('s','p','u','b');
-                        p_es->i_cat = SPU_ES;
+#endif
+                }
+                else if( (i_id & 0xF8FF) == 0x88BD )
+                {
+                    i_fourcc = VLC_FOURCC('d','t','s','b');
+                    i_cat = AUDIO_ES;
 #ifdef AUTO_SPAWN
-                        if( config_GetInt( p_input, "spu-channel" )
-                                == ((p_es->i_id & 0x1F00) >> 8) )
-                        {
-                            if( !p_input->stream.b_seekable )
-                                input_SelectES( p_input, p_es );
-                        }
+                    if( !p_input->stream.b_seekable )
+                    if( config_GetInt( p_input, "audio-channel" )
+                            == ((i_id & 0x700) >> 8) ||
+                        ( config_GetInt( p_input, "audio-channel" ) < 0
+                          && !((i_id & 0x700) >> 8)) )
+                    switch( config_GetInt( p_input, "audio-type" ) )
+                    {
+                    case -1:
+                    case REQUESTED_DTS:
+                        b_auto_spawn = VLC_TRUE;
+                    }
 #endif
+                }
+                else if( (i_id & 0xF0FF) == 0x80BD )
+                {
+                    /* A52 audio (0x80->0x8F) */
+                    i_fourcc = VLC_FOURCC('a','5','2','b');
+                    i_cat = AUDIO_ES;
+#ifdef AUTO_SPAWN
+                    if( !p_input->stream.b_seekable )
+                    if( config_GetInt( p_input, "audio-channel" )
+                            == ((i_id & 0xF00) >> 8) ||
+                        ( config_GetInt( p_input, "audio-channel" ) < 0
+                          && !((i_id & 0xF00) >> 8)) )
+                    switch( config_GetInt( p_input, "audio-type" ) )
+                    {
+                    case -1:
+                    case REQUESTED_A52:
+                        b_auto_spawn = VLC_TRUE;
                     }
-                    else if( (i_id & 0xF0FF) == 0xA0BD )
+#endif
+                }
+                else if( (i_id & 0xE0FF) == 0x20BD )
+                {
+                    /* Subtitles video (0x20->0x3F) */
+                    i_fourcc = VLC_FOURCC('s','p','u','b');
+                    i_cat = SPU_ES;
+#ifdef AUTO_SPAWN
+                    if( !p_input->stream.b_seekable )
+                    if( config_GetInt( p_input, "spu-channel" )
+                           == ((i_id & 0x1F00) >> 8) )
                     {
-                        /* LPCM audio (0xA0->0xAF) */
-                        p_es->i_fourcc = VLC_FOURCC('l','p','c','b');
-                        p_es->i_cat = AUDIO_ES;
+                        b_auto_spawn = VLC_TRUE;
                     }
-                    else
+#endif
+                }
+                else if( (i_id & 0xF0FF) == 0xA0BD )
+                {
+                    /* LPCM audio (0xA0->0xAF) */
+                    i_fourcc = VLC_FOURCC('l','p','c','b');
+                    i_cat = AUDIO_ES;
+                }
+                else if( (i_id & 0xFFFF) == 0x70BD )
+                {
+                    /* SVCD OGT subtitles in stream 0x070 */
+                    i_fourcc = VLC_FOURCC('o','g','t', ' ');
+                    i_cat = SPU_ES;
+#ifdef FINISHED_DEBUGGING
+                    if( !p_input->stream.b_seekable )
+                    if( config_GetInt( p_input, "spu-channel" )
+                           == ((i_id & 0x0300) >> 8) )
+#endif
                     {
-                        p_es->i_fourcc = 0;
+                        b_auto_spawn = VLC_TRUE;
                     }
                 }
+                else if( ((i_id >> 8) & 0xFF) <= 0x03 &&
+                         (i_id & 0x00FF) == 0x00BD )
+                {
+                    /* CVD subtitles (0x00->0x03) */
+                    i_fourcc = VLC_FOURCC('c','v','d', ' ');
+                    i_cat = SPU_ES;
+                    msg_Warn( p_input,
+                              "CVD subtitles not implemented yet" );
+                }
+                else
+                {
+                    i_cat = UNKNOWN_ES;
+                    i_fourcc = 0;
+                }
+
+                p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
+                                    i_id, i_cat, NULL, 0 );
+
+                p_es->i_stream_id = p_data->p_demux_start[3];
+                p_es->i_fourcc = i_fourcc;
+
+                if( b_auto_spawn ) input_SelectES( p_input, p_es );
 
                 /* Tell the interface the stream has changed */
                 p_input->stream.b_changed = 1;
@@ -935,13 +1017,13 @@ static es_descriptor_t * ParsePS( input_thread_t * p_input,
  *****************************************************************************/
 static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
 {
-    u32                 i_code;
-    vlc_bool_t          b_trash = 0;
-    es_descriptor_t *   p_es = NULL;
+    uint32_t i_code;
+    vlc_bool_t b_trash = 0;
+    es_descriptor_t * p_es = NULL;
 
-    i_code = ((u32)p_data->p_demux_start[0] << 24)
-                | ((u32)p_data->p_demux_start[1] << 16)
-                | ((u32)p_data->p_demux_start[2] << 8)
+    i_code = ((uint32_t)p_data->p_demux_start[0] << 24)
+                | ((uint32_t)p_data->p_demux_start[1] << 16)
+                | ((uint32_t)p_data->p_demux_start[2] << 8)
                 | p_data->p_demux_start[3];
     if( i_code <= 0x1BC )
     {
@@ -950,8 +1032,8 @@ static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
         case 0x1BA: /* PACK_START_CODE */
             {
                 /* Read the SCR. */
-                mtime_t         scr_time;
-                u32             i_mux_rate;
+                mtime_t scr_time;
+                uint32_t i_mux_rate;
 
                 if( (p_data->p_demux_start[4] & 0xC0) == 0x40 )
                 {
@@ -976,7 +1058,7 @@ static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
                                         >> 11);
 
                     /* mux_rate */
-                    i_mux_rate = ((u32)U16_AT(p_header + 10) << 6)
+                    i_mux_rate = ((uint32_t)U16_AT(p_header + 10) << 6)
                                    | (p_header[12] >> 2);
                     /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
                      * This is the biggest kludge ever !
@@ -1033,11 +1115,11 @@ static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
             DecodePSM( p_input, p_data );
             b_trash = 1;
             break;
-    
+
         case 0x1B9: /* PROGRAM_END_CODE */
             b_trash = 1;
             break;
-   
+
         default:
             /* This should not happen */
             b_trash = 1;
@@ -1050,7 +1132,7 @@ static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
         p_es = ParsePS( p_input, p_data );
 
         vlc_mutex_lock( &p_input->stream.control.control_lock );
-        if( p_es != NULL && p_es->p_decoder_fifo != NULL
+        if( p_es != NULL && p_es->p_dec != NULL
              && (p_es->i_cat != AUDIO_ES || !p_input->stream.control.b_mute) )
         {
             vlc_mutex_unlock( &p_input->stream.control.control_lock );
@@ -1072,7 +1154,7 @@ static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
     }
 }
 
+
 /*
  * TS Demultiplexing
  */
@@ -1140,18 +1222,21 @@ static ssize_t ReadTS( input_thread_t * p_input, data_packet_t ** pp_data )
 static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
                      psi_callback_t pf_psi_callback )
 {
-    u16                 i_pid;
-    int                 i_dummy;
+    uint16_t            i_pid;
+    unsigned int        i_dummy;
     vlc_bool_t          b_adaptation;         /* Adaptation field is present */
     vlc_bool_t          b_payload;                 /* Packet carries payload */
     vlc_bool_t          b_unit_start;  /* A PSI or a PES start in the packet */
     vlc_bool_t          b_trash = 0;             /* Is the packet unuseful ? */
     vlc_bool_t          b_lost = 0;             /* Was there a packet loss ? */
     vlc_bool_t          b_psi = 0;                        /* Is this a PSI ? */
+    vlc_bool_t          b_dvbsub = 0;            /* Is this a dvb subtitle ? */
     vlc_bool_t          b_pcr = 0;                   /* Does it have a PCR ? */
     es_descriptor_t *   p_es = NULL;
     es_ts_data_t *      p_es_demux = NULL;
     pgrm_ts_data_t *    p_pgrm_demux = NULL;
+    stream_ts_data_t *  p_stream_demux =
+                          (stream_ts_data_t *)p_input->stream.p_demux_data;
 
 #define p (p_data->p_demux_start)
     /* Extract flags values from TS common header. */
@@ -1160,9 +1245,15 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
     b_adaptation = (p[3] & 0x20);
     b_payload = (p[3] & 0x10);
 
+    /* Was there a transport error ? */
+    if ( p[1] & 0x80 )
+    {
+        msg_Warn( p_input, "transport_error_indicator set for PID %d counter %x", i_pid, p[3] & 0x0f );
+    }
+
     /* Find out the elementary stream. */
     vlc_mutex_lock( &p_input->stream.stream_lock );
-    
+
     for( i_dummy = 0; i_dummy < p_input->stream.i_pgrm_number; i_dummy ++ )
     {
         if( (( pgrm_ts_data_t * ) p_input->stream.pp_programs[i_dummy]->
@@ -1172,20 +1263,24 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
             break;
         }
     }
-            
-    p_es= input_FindES( p_input, i_pid );
-    
+
+    p_es = input_FindES( p_input, i_pid );
+
     if( (p_es != NULL) && (p_es->p_demux_data != NULL) )
     {
         p_es_demux = (es_ts_data_t *)p_es->p_demux_data;
-        
+
         if( p_es_demux->b_psi )
         {
             b_psi = 1;
         }
+        else if ( p_es_demux->b_dvbsub )
+        {
+            b_dvbsub = 1;
+        }
         else
         {
-            p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data; 
+            p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;
         }
     }
 
@@ -1196,20 +1291,20 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
         /* Not selected. Just read the adaptation field for a PCR. */
         b_trash = 1;
     }
-    else if( p_es->p_decoder_fifo == NULL && !b_psi )
+    else if( p_es->p_dec == NULL && !b_psi && !b_dvbsub )
     {
-        b_trash = 1; 
+        b_trash = 1;
     }
 
     vlc_mutex_unlock( &p_input->stream.control.control_lock );
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
 
-    /* Don't change the order of the tests : if b_psi then p_pgrm_demux 
+    /* Don't change the order of the tests : if b_psi then p_pgrm_demux
      * may still be null. Who said it was ugly ?
      * I have written worse. --Meuuh */
-    if( ( p_es  ) && 
-        ((p_es->p_decoder_fifo != NULL) || b_psi || b_pcr ) )
+    if( ( p_es ) &&
+        ((p_es->p_dec != NULL) || b_psi || b_pcr || b_dvbsub) )
     {
         p_es->c_packets++;
 
@@ -1225,7 +1320,7 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
         {
             /* p[4] is adaptation_field_length minus one */
             p_data->p_payload_start += 5 + p[4];
-    
+
             /* The adaptation field can be limited to the
              * adaptation_field_length byte, so that there is nothing to do:
              * skip this possibility */
@@ -1237,12 +1332,19 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
                  * 183 bytes. */
                 if( b_payload ? (p[4] > 182) : (p[4] != 183) )
                 {
-                    msg_Warn( p_input, "invalid TS adaptation field (%p)",
-                              p_data );
+                    msg_Warn( p_input, "invalid TS adaptation field for PID %d (%2x)",
+                              i_pid, p[4] );
                     p_data->b_discard_payload = 1;
                     p_es->c_invalid_packets++;
+
+                    /* The length was invalid so we shouldn't have added it to
+                     * p_payload_start above.  Ensure p_payload_start has a
+                     * valid value by setting it equal to p_payload_end.  This
+                     * also stops any data being processed from the packet.
+                     */
+                    p_data->p_payload_start = p_data->p_payload_end;
                 }
-    
+
                 /* Now we are sure that the byte containing flags is present:
                  * read it */
                 else
@@ -1252,26 +1354,29 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
                     {
                         msg_Warn( p_input,
                             "discontinuity_indicator encountered by TS demux "
-                            "(position read: %d, saved: %d)",
-                            p[5] & 0x80, p_es_demux->i_continuity_counter );
-    
+                            "(PID %d: current %d, packet %d)",
+                            i_pid,
+                            ( p_es_demux->i_continuity_counter ) & 0x0f,
+                            p[3] & 0x0f );
+
                         /* If the PID carries the PCR, there will be a system
                          * time-based discontinuity. We let the PCR decoder
                          * handle that. */
                         p_es->p_pgrm->i_synchro_state = SYNCHRO_REINIT;
-    
-                        /* There also may be a continuity_counter
-                         * discontinuity: resynchronize our counter with
-                         * the one of the stream. */
-                        p_es_demux->i_continuity_counter = (p[3] & 0x0f) - 1;
+
+                        /* Don't resynchronise the counter here - it will
+                         * be checked later and b_lost will then be set if
+                         * necessary.
+                         */
                     }
-    
+
                 } /* valid TS adaptation field ? */
             } /* length > 0 */
         } /* has adaptation field */
         /* Check the continuity of the stream. */
         i_dummy = ((p[3] & 0x0f) - p_es_demux->i_continuity_counter) & 0x0f;
-        if( i_dummy == 1 )
+        if( b_payload &&
+                ( i_dummy == 1 || (b_psi && p_stream_demux->b_buggy_psi ) ) )
         {
             /* Everything is ok, just increase our counter */
             (p_es_demux->i_continuity_counter)++;
@@ -1286,11 +1391,19 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
                  * the packet. */
                 b_trash = 1;
             }
+            else if( !b_payload )
+            {
+                /* If there is no payload, the counter should be unchanged */
+                msg_Warn( p_input, "packet rxd for PID %d with no payload but "
+                        "wrong counter: current %d, packet %d", i_pid,
+                        p_es_demux->i_continuity_counter & 0x0f, p[3] & 0x0f );
+            }
             else if( i_dummy <= 0 )
             {
                 /* Duplicate packet: mark it as being to be trashed. */
                 msg_Warn( p_input,
-                          "duplicate packet received by TS demux" );
+                          "duplicate packet received for PID %d (counter %d)",
+                          p_es->i_id, p[3] & 0x0f );
                 b_trash = 1;
             }
             else if( p_es_demux->i_continuity_counter == 0xFF )
@@ -1310,7 +1423,8 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
                  * as we don't know, do as if we missed a packet to be sure
                  * to recover from this situation */
                 msg_Warn( p_input,
-                          "packet lost by TS demux: current %d, packet %d",
+                          "packet lost by TS demux for PID %d: current %d, packet %d",
+                          i_pid,
                           p_es_demux->i_continuity_counter & 0x0f,
                           p[3] & 0x0f );
                 b_lost = 1;
@@ -1318,7 +1432,7 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
             } /* not continuous */
         } /* continuity */
     } /* if selected or PCR */
-    
+
     /* Handle PCR */
     if( b_pcr && b_adaptation && (p[5] & 0x10) && p[4]>=7 )
     {
@@ -1330,7 +1444,7 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
                    ( (mtime_t)p[9] << 1 ) |
                    ( (mtime_t)p[10] >> 7 );
         /* Call the pace control. */
-        for( i_dummy = 0; i_dummy < p_input->stream.i_pgrm_number; 
+        for( i_dummy = 0; i_dummy < p_input->stream.i_pgrm_number;
                                 i_dummy ++ )
         {
             if( ( ( pgrm_ts_data_t * ) p_input->stream.pp_programs[i_dummy]->
@@ -1342,7 +1456,7 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
         }
 
     }
-    
+
     /* Trash the packet if it has no payload or if it isn't selected */
     if( b_trash )
     {
@@ -1359,7 +1473,7 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
         else
         {
             /* The payload carries a PES stream */
-            GatherPES( p_input, p_data, p_es, b_unit_start, b_lost ); 
+            GatherPES( p_input, p_data, p_es, b_unit_start, b_lost );
         }
 
     }
@@ -1367,4 +1481,3 @@ static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,
 #undef p
 
 }
-