]> git.sesse.net Git - vlc/blobdiff - src/input/mpeg_system.c
* IPv6 network module, courtesy of Alexis Guillard <alexis.guillard@bt.com>,
[vlc] / src / input / mpeg_system.c
index bf58fc0a96d5cfff1ab459d7921b83554f9ae31b..8b594aba4755a46a4548a96f0a70cd4be924e5d4 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_system.c: TS, PS and PES management
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: mpeg_system.c,v 1.81 2002/03/01 00:33:18 massiot Exp $
+ * $Id: mpeg_system.c,v 1.82 2002/03/04 23:56:37 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -639,6 +639,110 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 }
 
+/*****************************************************************************
+ * input_ReadPS: store a PS packet into a data_buffer_t
+ *****************************************************************************/
+#define PEEK( SIZE )                                                        \
+    i_error = input_Peek( p_input, &p_peek, SIZE );                         \
+    if( i_error == -1 )                                                     \
+    {                                                                       \
+        return( -1 );                                                       \
+    }                                                                       \
+    else if( i_error < SIZE )                                               \
+    {                                                                       \
+        /* EOF */                                                           \
+        return( 0 );                                                        \
+    }
+
+ssize_t input_ReadPS( input_thread_t * p_input, data_packet_t ** pp_data )
+{
+    byte_t *            p_peek;
+    size_t              i_packet_size;
+    ssize_t             i_error, i_read;
+
+    /* Read what we believe to be a packet header. */
+    PEEK( 4 );
+
+    if( *p_peek || *(p_peek + 1) || *(p_peek + 2) != 1 )
+    {
+        if( *p_peek || *(p_peek + 1) || *(p_peek + 2) )
+        {
+            /* 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( 3, "input warning: garbage at input (0x%x%x%x%x)",
+                 *p_peek, *(p_peek + 1), *(p_peek + 2), *(p_peek + 3) );
+        }
+
+        /* This is not the startcode of a packet. Read the stream
+         * until we find one. */
+        while( *p_peek || *(p_peek + 1) || *(p_peek + 2) != 1 )
+        {
+            p_input->p_current_data++;
+            PEEK( 4 );
+        }
+        /* Packet found. */
+    }
+
+    /* 0x1B9 == SYSTEM_END_CODE, it is only 4 bytes long. */
+    if( p_peek[3] != 0xB9 )
+    {
+        /* The packet is at least 6 bytes long. */
+        PEEK( 6 );
+
+        if( p_peek[3] != 0xBA )
+        {
+            /* That's the case for all packets, except pack header. */
+            i_packet_size = (p_peek[4] << 8) | p_peek[5];
+        }
+        else
+        {
+            /* Pack header. */
+            if( (p_peek[4] & 0xC0) == 0x40 )
+            {
+                /* MPEG-2 */
+                i_packet_size = 8;
+            }
+            else if( (p_peek[4] & 0xF0) == 0x20 )
+            {
+                /* MPEG-1 */
+                i_packet_size = 6;
+            }
+            else
+            {
+                intf_ErrMsg( "Unable to determine stream type" );
+                return( -1 );
+            }
+        }
+    }
+    else
+    {
+        /* System End Code */
+        i_packet_size = -2;
+    }
+
+    /* Fetch a packet of the appropriate size. */
+    i_read = input_SplitBuffer( p_input, pp_data, i_packet_size + 6 );
+    if( i_read <= 0 )
+    {
+        return( i_read );
+    }
+
+    /* In MPEG-2 pack headers we still have to read stuffing bytes. */
+    if( ((*pp_data)->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )
+    {
+        size_t i_stuffing = ((*pp_data)->p_demux_start[13] & 0x7);
+        /* Force refill of the input buffer - though we don't care
+         * about p_peek. Please note that this is unoptimized. */
+        PEEK( i_stuffing );
+        p_input->p_current_data += i_stuffing;
+    }
+
+    return( 1 );
+}
+
+#undef PEEK
+
 /*****************************************************************************
  * input_ParsePS: read the PS header
  *****************************************************************************/
@@ -923,6 +1027,63 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
  * TS Demultiplexing
  */
 
+/*****************************************************************************
+ * input_ReadTS: store a TS packet into a data_buffer_t
+ *****************************************************************************/
+#define PEEK( SIZE )                                                        \
+    i_error = input_Peek( p_input, &p_peek, SIZE );                         \
+    if( i_error == -1 )                                                     \
+    {                                                                       \
+        return( -1 );                                                       \
+    }                                                                       \
+    else if( i_error < SIZE )                                               \
+    {                                                                       \
+        /* EOF */                                                           \
+        return( 0 );                                                        \
+    }
+
+ssize_t input_ReadTS( input_thread_t * p_input, data_packet_t ** pp_data )
+{
+    byte_t *            p_peek;
+    ssize_t             i_error, i_read;
+
+    PEEK( 1 );
+
+    if( *p_peek != TS_SYNC_CODE )
+    {
+        intf_WarnMsg( 3, "input warning: garbage at input (%x)", *p_peek );
+
+        if( p_input->i_mtu )
+        {
+            while( *p_peek != TS_SYNC_CODE )
+            {
+                /* Try to resync on next packet. */
+                PEEK( TS_PACKET_SIZE );
+                p_input->p_current_data += TS_PACKET_SIZE;
+                PEEK( 1 );
+            }
+        }
+        else
+        {
+            /* Move forward until we find 0x47 (and hope it's the good
+             * one... FIXME) */
+            while( *p_peek != TS_SYNC_CODE )
+            {
+                p_input->p_current_data++;
+                PEEK( 1 );
+            }
+        }
+    }
+
+    i_read = input_SplitBuffer( p_input, pp_data, TS_PACKET_SIZE );
+    if( i_read <= 0 )
+    {
+        return( i_read );
+    }
+
+    return( 1 );
+}
+
 /*****************************************************************************
  * input_DemuxTS: first step of demultiplexing: the TS header
  *****************************************************************************/