]> git.sesse.net Git - vlc/commitdiff
* Big cleanup of the PS input plugin ;
authorChristophe Massiot <massiot@videolan.org>
Wed, 20 Dec 2000 16:04:31 +0000 (16:04 +0000)
committerChristophe Massiot <massiot@videolan.org>
Wed, 20 Dec 2000 16:04:31 +0000 (16:04 +0000)
* Fixed a bug in AC3 initialization ;
* PS streams are now pre-parsed (this can take a while) if possible ;

./configure is required after this update.

include/config.h.in
include/input_ext-intf.h
src/ac3_decoder/ac3_decoder_thread.c
src/input/input.c
src/input/input.h
src/input/input_programs.c
src/input/input_ps.c
src/input/mpeg_system.c
src/input/mpeg_system.h

index 5ea4e4dfef5083d51e25114355f83ace4dd28acc..caa7d5dc1e7ca68d390ad98986d0f884ff87b2c2 100644 (file)
 /* Maximum number of selected ES in an input thread */
 #define INPUT_MAX_SELECTED_ES           10
 
+/* Maximum size of a data packet (128 kB) */
+#define INPUT_MAX_PACKET_SIZE                  131072
+
 /* Maximum number of TS packets in the client at any time
  * INPUT_MAX_TS + 1 must be a power of 2, to optimize the %(INPUT_MAX_TS+1)
  * operation with a &INPUT_MAX_TS in the case of a fifo netlist.
index e570531410a272fcad644ba1371fdf9de9c79540..67eb43c0d5075e37194dbb7d18e70852665483c7 100644 (file)
@@ -1,4 +1,27 @@
-/* Structures exported to the interface */
+/*****************************************************************************
+ * input_ext-intf.h: structures of the input exported to the interface
+ * This header provides structures to read the stream descriptors and
+ * control the pace of reading. 
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: input_ext-intf.h,v 1.4 2000/12/20 16:04:31 massiot Exp $
+ *
+ * Authors:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
 
 /*
  * Communication input -> interface
@@ -54,8 +77,10 @@ typedef struct es_descriptor_s
 #define MPEG1_AUDIO_ES      0x03
 #define MPEG2_AUDIO_ES      0x04
 #define AC3_AUDIO_ES        0x81
-#define DVD_SPU_ES          0x82              /* 0x82 might violate the norm */
+/* These ones might violate the norm : */
+#define DVD_SPU_ES          0x82
 #define LPCM_AUDIO_ES       0x83
+#define UNKNOWN_ES         0xFF
 
 /*****************************************************************************
  * pgrm_descriptor_t
index 98c7e7107dd7d0efdc55785b341bb719f79115f9..459b774a911201b24d298f3c47159e4d8c02fcfa 100644 (file)
@@ -126,6 +126,17 @@ static int InitThread (ac3dec_thread_t * p_ac3dec)
 
     intf_DbgMsg ("ac3dec debug: initializing ac3 decoder thread %p\n", p_ac3dec);
 
+    /* Get the first data packet. */
+    vlc_mutex_lock( &p_ac3dec->p_fifo->data_lock );
+    while ( DECODER_FIFO_ISEMPTY( *p_ac3dec->p_fifo ) )
+    {
+        if ( p_ac3dec->p_fifo->b_die )
+        {
+            vlc_mutex_unlock( &p_ac3dec->p_fifo->data_lock );
+            return -1;
+        }
+        vlc_cond_wait( &p_ac3dec->p_fifo->data_wait, &p_ac3dec->p_fifo->data_lock );
+    }
     p_ac3dec->p_data = DECODER_FIFO_START(*p_ac3dec->p_fifo)->p_first;
     byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder);
     byte_stream->p_byte = p_ac3dec->p_data->p_payload_start;
index 517aaddcba6ad61029d811cacf0a8854f0720e49..8a13215e34beaccce7b57f47cc7e2baf9421dee5 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input.c,v 1.59 2000/12/19 19:08:51 massiot Exp $
+ * $Id: input.c,v 1.60 2000/12/20 16:04:31 massiot Exp $
  *
  * Authors: 
  *
@@ -176,7 +176,8 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
  *****************************************************************************/
 static void RunThread( input_thread_t *p_input )
 {
-    data_packet_t *      pp_packets[INPUT_READ_ONCE];
+    data_packet_t *         pp_packets[INPUT_READ_ONCE];
+    int                     i_error, i;
 
     InitThread( p_input );
 
@@ -195,15 +196,23 @@ static void RunThread( input_thread_t *p_input )
         }
         vlc_mutex_unlock( &p_input->stream.control.control_lock );
 
-        p_input->p_plugin->pf_read( p_input, pp_packets );
-        if( !p_input->b_error )
+        i_error = p_input->p_plugin->pf_read( p_input, pp_packets );
+
+        /* Demultiplex read packets. */
+        for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
         {
-            int     i;
+            p_input->p_plugin->pf_demux( p_input, pp_packets[i] );
+        }
 
-            for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
+        if( i_error )
+        {
+            if( i_error == 1 )
             {
-                p_input->p_plugin->pf_demux( p_input, pp_packets[i] );
+                /* End of file */
+                intf_WarnMsg( 1, "End of file reached" );
+                /* FIXME: don't treat that as an error */
             }
+            p_input->b_error = 1;
         }
     }
 
index 0c7352552c9d7428fad1c5cb50bbc5dde85998db..848f3f6c14a861e59aa8ee971bf0ee6212be3318 100644 (file)
@@ -1,5 +1,31 @@
-/* Communication plugin -> input */
+/*****************************************************************************
+ * input.h: structures of the input not exported to other modules
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: input.h,v 1.4 2000/12/20 16:04:31 massiot Exp $
+ *
+ * Authors:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*
+ * Communication plugin -> input
+ */
 
+/* FIXME: you've gotta move this move this, you've gotta move this move this */
 #define INPUT_READ_ONCE     7   /* We live in a world dominated by Ethernet. *
                                  * Ethernet MTU is 1500 bytes, so in a UDP   *
                                  * packet we can put : 1500/188 = 7 TS       *
@@ -22,7 +48,7 @@ typedef struct input_capabilities_s
     void                 (* pf_end)( struct input_thread_s * );
 
     /* Read & Demultiplex */
-    void                 (* pf_read)( struct input_thread_s *,
+    int                  (* pf_read)( struct input_thread_s *,
                           struct data_packet_s * pp_packets[INPUT_READ_ONCE] );
     void                 (* pf_demux)( struct input_thread_s *,
                                        struct data_packet_s * );
@@ -54,6 +80,7 @@ void input_InitStream( struct input_thread_s *, size_t );
 struct pgrm_descriptor_s * input_AddProgram( struct input_thread_s *,
                                              u16, size_t );
 void input_DelProgram( struct input_thread_s *, u16 );
+void input_DumpStream( struct input_thread_s * );
 struct es_descriptor_s * input_AddES( struct input_thread_s *,
                                       struct pgrm_descriptor_s *, u16,
                                       size_t );
index 8160472abdcde571aad1a6b26f597bb343e8e515..e228ea6c69d01ab59b17841235a0be10323b3c26 100644 (file)
@@ -2,7 +2,7 @@
  * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_programs.c,v 1.4 2000/12/19 19:08:51 massiot Exp $
+ * $Id: input_programs.c,v 1.5 2000/12/20 16:04:31 massiot Exp $
  *
  * Authors:
  *
@@ -51,6 +51,7 @@
  *****************************************************************************/
 void input_InitStream( input_thread_t * p_input, size_t i_data_len )
 {
+    p_input->stream.i_stream_id = 0;
     p_input->stream.i_pgrm_number = 0;
     p_input->stream.pp_programs = NULL;
 
@@ -283,6 +284,44 @@ void input_DelES( input_thread_t * p_input, u16 i_id )
     }
 }
 
+#ifdef STATS
+/*****************************************************************************
+ * input_DumpStream: dumps the contents of a stream descriptor
+ *****************************************************************************/
+void input_DumpStream( input_thread_t * p_input )
+{
+    int i, j;
+#define S   p_input->stream
+    intf_Msg( "input info: Dumping stream ID 0x%x\n", S.i_stream_id );
+    if( S.b_seekable )
+        intf_Msg( "input info: seekable stream, position: %d/%d\n",
+                  S.i_tell, S.i_size );
+    else
+        intf_Msg( "input info: %s\n", S.b_pace_control ? "pace controlled" :
+                  "pace un-controlled" );
+#undef S
+    for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
+    {
+#define P   p_input->stream.pp_programs[i]
+        intf_Msg( "input info: Dumping program 0x%x, version %d (%s)\n",
+                  P->i_number, P->i_version,
+                  P->b_is_ok ? "complete" : "partial" );
+        if( P->i_synchro_state == SYNCHRO_OK )
+            intf_Msg( "input info: synchro absolute delta : %lld (jitter : %lld)\n",
+                      P->delta_absolute, P->delta_cr );
+#undef P
+        for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
+        {
+#define ES  p_input->stream.pp_programs[i]->pp_es[j]
+            intf_Msg( "input info: ES 0x%x, stream 0x%x, type 0x%x, %s\n",
+                      ES->i_id, ES->i_stream_id, ES->i_type,
+                      ES->p_decoder_fifo != NULL ? "selected" : "not selected");
+#undef ES
+        }
+    }
+}
+#endif
+
 /*****************************************************************************
  * InitDecConfig: initializes a decoder_config_t
  *****************************************************************************/
index 5647c4a83f5b7ffe9e84d75612c4dceaef0d258d..958433451201d88225b1b60c6e4319d834880752 100644 (file)
@@ -2,6 +2,7 @@
  * input_ps.c: PS demux and packet management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
+ * $Id: input_ps.c,v 1.7 2000/12/20 16:04:31 massiot Exp $
  *
  * Authors: 
  *
@@ -52,7 +53,7 @@
  * Local prototypes
  *****************************************************************************/
 static int  PSProbe     ( struct input_thread_s * );
-static void PSRead      ( struct input_thread_s *,
+static int  PSRead      ( struct input_thread_s *,
                           data_packet_t * p_packets[INPUT_READ_ONCE] );
 static void PSInit      ( struct input_thread_s * );
 static void PSEnd       ( struct input_thread_s * );
@@ -100,10 +101,49 @@ static void PSInit( input_thread_t * p_input )
     }
     fseek( p_method->stream, 0, SEEK_SET );
 
-    /* Pre-parse the stream to gather stream_descriptor_t. */
-
     input_InitStream( p_input, 0 );
     input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
+
+    if( p_input->stream.b_seekable )
+    {
+        /* Pre-parse the stream to gather stream_descriptor_t. */
+        p_input->stream.pp_programs[0]->b_is_ok = 0;
+        /* FIXME: don't read all stream (it can be long !) */
+        while( !p_input->b_die && !p_input->b_error )
+        {
+            int                 i_result, i;
+            data_packet_t *     pp_packets[INPUT_READ_ONCE];
+
+            i_result = PSRead( p_input, pp_packets );
+            if( i_result == 1 ) break;
+            if( i_result == -1 )
+            {
+                p_input->b_error = 1;
+                break;
+            }
+
+            for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
+            {
+                /* FIXME: use i_p_config_t */
+                input_ParsePS( p_input, pp_packets[i] );
+            }
+        }
+        fseek( p_method->stream, 0, SEEK_SET );
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        p_input->stream.pp_programs[0]->b_is_ok = 1;
+        p_input->stream.i_tell = 0;
+#ifdef STATS
+        input_DumpStream( p_input );
+#endif
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    }
+    else
+    {
+        /* The programs will be added when we read them. */
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        p_input->stream.pp_programs[0]->b_is_ok = 0;
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    }
 }
 
 /*****************************************************************************
@@ -116,125 +156,157 @@ static void PSEnd( input_thread_t * p_input )
 }
 
 /*****************************************************************************
- * PSRead: reads a data packet
+ * SafeRead: reads a chunk of stream and correctly detects errors
  *****************************************************************************/
-/* FIXME: read INPUT_READ_ONCE packet at once */
-static void PSRead( input_thread_t * p_input,
-                    data_packet_t * p_packets[INPUT_READ_ONCE] )
+static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
+                                size_t i_len )
 {
-    byte_t              p_header[6];
-    data_packet_t *     p_data;
-    int                 i_packet_size;
     thread_ps_data_t *  p_method;
+    int                 i_error;
 
     p_method = (thread_ps_data_t *)p_input->p_method_data;
-
-    while( fread( p_header, 6, 1, p_method->stream ) != 1 )
+    while( fread( p_buffer, i_len, 1, p_method->stream ) != 1 )
     {
-        int             i_error;
-        if( (i_error = ferror( p_method->stream )) )
+        if( feof( p_method->stream ) )
         {
-            intf_ErrMsg( "Read 1 failed (%s)", strerror(i_error) );
-            p_input->b_error = 1;
-            return;
+            return( 1 );
         }
 
-        if( feof( p_method->stream ) )
+        if( (i_error = ferror( p_method->stream )) )
         {
-            intf_ErrMsg( "EOF reached" );
-            p_input->b_error = 1;
-            return;
+            intf_ErrMsg( "Read failed (%s)", strerror(i_error) );
+            return( -1 );
         }
     }
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_input->stream.i_tell += i_len;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    return( 0 );
+}
 
-    if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
+/*****************************************************************************
+ * PSRead: reads a data packet
+ *****************************************************************************
+ * Returns -1 in case of error, 0 if everything went well, and 1 in case of
+ * EOF.
+ *****************************************************************************/
+static int PSRead( input_thread_t * p_input,
+                   data_packet_t * pp_packets[INPUT_READ_ONCE] )
+{
+    byte_t              p_header[6];
+    data_packet_t *     p_data;
+    size_t              i_packet_size;
+    int                 i_packet, i_error;
+    thread_ps_data_t *  p_method;
+
+    p_method = (thread_ps_data_t *)p_input->p_method_data;
+
+    memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
+    for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
     {
-        u32         i_buffer = U32_AT(p_header);
-        intf_WarnMsg( 1, "Garbage at input (%x)\n", i_buffer );
-        while( (i_buffer & 0xFFFFFF00) != 0x100L )
+        /* Read what we believe to be a packet header. */
+        if( (i_error = SafeRead( p_input, p_header, 6 )) )
         {
-            i_buffer <<= 8;
-            i_buffer |= getc( p_method->stream );
-            if( feof(p_method->stream) || ferror(p_method->stream) )
-            {
-                p_input->b_error = 1;
-                return;
-            }
+            return( i_error );
         }
-        *(u32 *)p_header = U32_AT(&i_buffer);
-        fread( p_header + 4, 2, 1, p_method->stream );
-    }
 
-    if( U32_AT(p_header) != 0x1BA )
-    {
-        i_packet_size = U16_AT(&p_header[4]);
-    }
-    else
-    {
-        if( (p_header[4] & 0xC0) == 0x40 )
+        if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
         {
-            /* MPEG-2 */
-            i_packet_size = 8;
+            /* This is not the startcode of a packet. Read the stream
+             * until we find one. */
+            u32         i_startcode = U32_AT(p_header);
+            int         i_dummy;
+
+            if( i_startcode )
+            {
+                /* It is common for MPEG-1 streams to pad with zeros
+                 * (although it is forbidden by the recommendation), so
+                 * don't bother everybody in this case. */
+                intf_WarnMsg( 1, "Garbage at input (%x)\n", i_startcode );
+            }
+
+            while( (i_startcode & 0xFFFFFF00) != 0x100L )
+            {
+                i_startcode <<= 8;
+                if( (i_dummy = getc( p_method->stream )) != EOF )
+                {
+                    i_startcode |= i_dummy;
+                }
+                else
+                {
+                    return( 1 );
+                }
+            }
+            /* Packet found. */
+            *(u32 *)p_header = U32_AT(&i_startcode);
+            if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
+            {
+                return( i_error );
+            }
         }
-        else if( (p_header[4] & 0xF0) == 0x20 )
+
+        if( U32_AT(p_header) != 0x1BA )
         {
-            /* MPEG-1 */
-            i_packet_size = 6;
+            /* That's the case for all packets, except pack header. */
+            i_packet_size = U16_AT(&p_header[4]);
         }
         else
         {
-            intf_ErrMsg( "Unable to determine stream type" );
-            p_input->b_error = 1;
-            return;
+            /* Pack header. */
+            if( (p_header[4] & 0xC0) == 0x40 )
+            {
+                /* MPEG-2 */
+                i_packet_size = 8;
+            }
+            else if( (p_header[4] & 0xF0) == 0x20 )
+            {
+                /* MPEG-1 */
+                i_packet_size = 6;
+            }
+            else
+            {
+                intf_ErrMsg( "Unable to determine stream type" );
+                return( -1 );
+            }
         }
-    }
-
-    if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
-    {
-        p_input->b_error = 1;
-        intf_ErrMsg( "Out of memory" );
-        return;
-    }
 
-    memcpy( p_data->p_buffer, p_header, 6 );
-
-    /* FIXME: catch EINTR ! */
-    while( fread( p_data->p_buffer + 6, i_packet_size,
-               1, p_method->stream ) != 1 )
-    {
-        int             i_error;
-        if( (i_error = ferror( p_method->stream)) )
+        /* Fetch a packet of the appropriate size. */
+        if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
         {
-            intf_ErrMsg( "Read 1 failed (%s)", strerror(i_error) );
-            p_input->b_error = 1;
-            return;
+            intf_ErrMsg( "Out of memory" );
+            return( -1 );
         }
 
-        if( feof( p_method->stream ) )
+        /* Copy the header we already read. */
+        memcpy( p_data->p_buffer, p_header, 6 );
+
+        /* Read the remaining of the packet. */
+        if( (i_error =
+                SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
         {
-            intf_ErrMsg( "EOF reached" );
-            p_input->b_error = 1;
-            return;
+            return( i_error );
         }
-    }
 
-    if( U32_AT(p_header) == 0x1BA )
-    {
-        if( i_packet_size == 8 )
+        /* In MPEG-2 pack headers we still have to read stuffing bytes. */
+        if( U32_AT(p_header) == 0x1BA )
         {
-            /* MPEG-2 stuffing bytes */
-            byte_t      p_garbage[8];
-            if( (p_data->p_buffer[13] & 0x7) != 0 )
+            if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
             {
-                /* FIXME: catch EINTR ! */
-                fread( p_garbage, p_garbage[0] & 0x7, 1,
-                       p_method->stream );
+                /* MPEG-2 stuffing bytes */
+                byte_t      p_garbage[8];
+                if( (i_error = SafeRead( p_input, p_garbage,
+                                         p_data->p_buffer[13] & 0x7)) )
+                {
+                    return( i_error );
+                }
             }
         }
+
+        /* Give the packet to the other input stages. */
+        pp_packets[i_packet] = p_data;
     }
 
-    memset( p_packets, 0, sizeof(p_packets) );
-    p_packets[0] = p_data;
+    return( 0 );
 }
 
 
@@ -250,6 +322,13 @@ static struct data_packet_s * NewPacket( void * p_garbage,
 {
     data_packet_t * p_data;
 
+    /* Safety check */
+    if( i_size > INPUT_MAX_PACKET_SIZE )
+    {
+        intf_ErrMsg( "Packet too big (%d)", i_size );
+        return NULL;
+    }
+
     if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL )
     {
         intf_DbgMsg( "Out of memory" );
index 131fd32cbd4cdbcfb16e410eada6ea9b402ba340..cb05f36d0ef46c5d6ba55a262f2301bc43503977 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_system.c: TS, PS and PES management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: mpeg_system.c,v 1.9 2000/12/19 19:08:51 massiot Exp $
+ * $Id: mpeg_system.c,v 1.10 2000/12/20 16:04:31 massiot Exp $
  *
  * Authors: 
  *
@@ -748,6 +748,105 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
     }
 }
 
+/*****************************************************************************
+ * input_ParsePS: read the PS header
+ *****************************************************************************/
+es_descriptor_t * input_ParsePS( input_thread_t * p_input,
+                                 data_packet_t * p_data )
+{
+    u32                 i_code;
+    es_descriptor_t *   p_es = NULL;
+
+    i_code = U32_AT( p_data->p_buffer );
+    if( i_code > 0x1BC ) /* ES start code */
+    {
+        u16                 i_id;
+        int                 i_dummy;
+
+        /* This is a PES packet. Find out if we want it or not. */
+        i_id = GetID( p_data );
+
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        if( p_input->stream.pp_programs[0]->b_is_ok )
+        {
+            /* Look only at the selected ES. */
+            for( i_dummy = 0; i_dummy < INPUT_MAX_SELECTED_ES; i_dummy++ )
+            {
+                if( p_input->pp_selected_es[i_dummy] != NULL
+                    && p_input->pp_selected_es[i_dummy]->i_id == i_id )
+                {
+                    p_es = p_input->pp_selected_es[i_dummy];
+                    break;
+                }
+            }
+        }
+        else
+        {
+            /* Search all ES ; if not found -> AddES */
+            for( i_dummy = 0; i_dummy < INPUT_MAX_ES; i_dummy++ )
+            {
+                if( p_input->p_es[i_dummy].i_id != EMPTY_ID 
+                    && p_input->p_es[i_dummy].i_id == i_id )
+                {
+                    p_es = &p_input->p_es[i_dummy];
+                    break;
+                }
+            }
+
+            if( p_es == NULL )
+            {
+                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_buffer[3];
+
+                    /* Set stream type and auto-spawn. */
+                    if( (i_id & 0xF0) == 0xE0 )
+                    {
+                        /* MPEG video */
+                        p_es->i_type = MPEG2_VIDEO_ES;
+#ifdef AUTO_SPAWN
+                        input_SelectES( p_input, p_es );
+#endif
+                    }
+                    else if( (i_id & 0xE0) == 0xC0 )
+                    {
+                        /* MPEG audio */
+                        p_es->i_type = MPEG2_AUDIO_ES;
+#ifdef AUTO_SPAWN
+                        input_SelectES( p_input, p_es );
+#endif
+                    }
+                    else if( (i_id & 0xF0FF) == 0x80BD )
+                    {
+                        /* AC3 audio */
+                        p_es->i_type = AC3_AUDIO_ES;
+#ifdef AUTO_SPAWN
+                        input_SelectES( p_input, p_es );
+#endif
+                    }
+                    else if( (i_id & 0xF0FF) == 0x20BD )
+                    {
+                        /* Subtitles video */
+                        p_es->i_type = DVD_SPU_ES;
+#ifdef AUTO_SPAWN
+                        input_SelectES( p_input, p_es );
+#endif
+                    }
+                    else
+                    {
+                        p_es->i_type = UNKNOWN_ES;
+                    }
+                }
+            }
+        } /* stream.b_is_ok */
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    } /* i_code > 0xBC */
+
+    return( p_es );
+}
+
 /*****************************************************************************
  * input_DemuxPS: first step of demultiplexing: the PS header
  *****************************************************************************/
@@ -758,7 +857,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
     es_descriptor_t *   p_es = NULL;
 
     i_code = U32_AT( p_data->p_buffer );
-    if( i_code >= 0x1B9 && i_code <= 0x1BC )
+    if( i_code <= 0x1BC )
     {
         switch( i_code )
         {
@@ -819,99 +918,9 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
     }
     else
     {
-        u16                 i_id;
-        int                 i_dummy;
-
-        /* This is a PES packet. Find out if we want it or not. */
-        i_id = GetID( p_data );
-
-        vlc_mutex_lock( &p_input->stream.stream_lock );
-#if 1
-        for( i_dummy = 0; i_dummy < INPUT_MAX_ES; i_dummy++ )
-        {
-            if( p_input->p_es[i_dummy].i_id != EMPTY_ID 
-                && p_input->p_es[i_dummy].i_id == i_id )
-            {
-                p_es = &p_input->p_es[i_dummy];
-                break;
-            }
-        }
-#else
-        for( i_dummy = 0; i_dummy < INPUT_MAX_SELECTED_ES; i_dummy++ )
-        {
-            if( p_input->pp_selected_es[i_dummy] != NULL
-                && p_input->pp_selected_es[i_dummy]->i_id == i_id )
-            {
-                p_es = p_input->pp_selected_es[i_dummy];
-                break;
-            }
-        }
-#endif
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-        if( p_es == NULL )
-        {
-#if 1
-            vlc_mutex_lock( &p_input->stream.stream_lock );
-            p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
-                                i_id, 0 );
-
-            if( p_es != NULL )
-            {
-                if( (i_id & 0xF0) == 0xE0 )
-                {
-                    /* MPEG video */
-                    p_es->i_stream_id = i_id;
-                    p_es->i_type = MPEG2_VIDEO_ES;
-
-#ifdef AUTO_SPAWN
-                    input_SelectES( p_input, p_es );
-#endif
-                }
-                else if( (i_id & 0xE0) == 0xC0 )
-                {
-                    /* MPEG audio */
-                    p_es->i_stream_id = i_id;
-                    p_es->i_type = MPEG2_AUDIO_ES;
-
-#ifdef AUTO_SPAWN
-                    input_SelectES( p_input, p_es );
-#endif
-                }
-                else if( (i_id & 0xF0FF) == 0x80BD )
-                {
-                    /* AC3 audio */
-                    p_es->i_stream_id = 0xBD;
-                    p_es->i_type = AC3_AUDIO_ES;
-
-#ifdef AUTO_SPAWN
-                    input_SelectES( p_input, p_es );
-#endif
-                }
-                else if( (i_id & 0xF0FF) == 0x20BD )
-                {
-                    /* Subtitles video */
-                    p_es->i_stream_id = 0xBD;
-                    p_es->i_type = DVD_SPU_ES;
-
-#ifdef AUTO_SPAWN
-                    input_SelectES( p_input, p_es );
-#endif
-                }
-                else
-                {
-                    b_trash = 1;
-                }
-                vlc_mutex_unlock( &p_input->stream.stream_lock );
-            }
-            else
-                b_trash = 1;
-#else
-            b_trash = 1;
-#endif
-        }
+        p_es = input_ParsePS( p_input, p_data );
 
-        if( p_es->p_decoder_fifo != NULL && !b_trash )
+        if( p_es != NULL && p_es->p_decoder_fifo != NULL && !b_trash )
         {
 #ifdef STATS
             p_es->c_packets++;
index f1f18555b9868cfea1deabc7112e4244d25e8bad..456af7507e3804302f12cb0011f6b86590f78233 100644 (file)
@@ -1,3 +1,27 @@
+/*****************************************************************************
+ * mpeg_system.h: structures of the input used to parse MPEG-1, MPEG-2 PS
+ * and TS system layers
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: mpeg_system.h,v 1.2 2000/12/20 16:04:31 massiot Exp $
+ *
+ * Authors:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
 /*****************************************************************************
  * Constants
  *****************************************************************************/
@@ -91,5 +115,7 @@ void input_DecodePES( struct input_thread_s *, struct es_descriptor_s * );
 void input_ParsePES( struct input_thread_s *, struct es_descriptor_s * );
 void input_GatherPES( struct input_thread_s *, struct data_packet_s *,
                       struct es_descriptor_s *, boolean_t, boolean_t );
+es_descriptor_t * input_ParsePS( struct input_thread_s *,
+                                 struct data_packet_s * );
 void input_DemuxPS( struct input_thread_s *, struct data_packet_s * );
 void input_DemuxTS( struct input_thread_s *, struct data_packet_s * );