]> git.sesse.net Git - vlc/commitdiff
Begining of TS Input
authorHenri Fallon <henri@videolan.org>
Wed, 14 Feb 2001 15:58:29 +0000 (15:58 +0000)
committerHenri Fallon <henri@videolan.org>
Wed, 14 Feb 2001 15:58:29 +0000 (15:58 +0000)
Done :
- fixed netlist
- embryo : support TS video trough file ( kludgy ... )

Next :
- Write DecodePSI and DemuxPSI, wich will clean the kludges off

Then :
- Write NetworkOpen ( shouldn't be difficult )

Eventually :
- Deal with lost/corrupt packets

include/input_netlist.h
plugins/dvd/input_dvd.c
plugins/mpeg/input_ts.c
plugins/mpeg/input_ts.h [new file with mode: 0644]
src/input/input_netlist.c
src/input/mpeg_system.c

index 301d5e1c259254cc43fa5341d76b8bca83d6082f..105af6088dfc145cbf7cb9eb8b9a3ed717e10991 100644 (file)
@@ -36,8 +36,9 @@ int                     input_NetlistInit( struct input_thread_s *,
                                            int i_nb_data, int i_nb_pes,
                                            size_t i_buffer_size,
                                            int i_read_once );
-struct iovec *          input_NetlistGetiovec( void *, struct data_packet_s** );
-void                    input_NetlistMviovec( void *, size_t );
+
+struct iovec * input_NetlistGetiovec( void * p_method_data );
+void input_NetlistMviovec( void * , size_t, struct data_packet_s **);
 struct data_packet_s *  input_NetlistNewPacket( void *, size_t );
 struct pes_packet_s *   input_NetlistNewPES( void * );
 void            input_NetlistDeletePacket( void *, struct data_packet_s * );
index 0aee39d9dbf1510c2a099b48fd8e51736f4125c6..4bd1ba0c9631e695ae1655c0210de6fbf04f4868 100644 (file)
@@ -10,7 +10,7 @@
  *  -dvd_udf to find files
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: input_dvd.c,v 1.10 2001/02/14 04:11:01 stef Exp $
+ * $Id: input_dvd.c,v 1.11 2001/02/14 15:58:29 henri Exp $
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
@@ -475,7 +475,7 @@ static int DVDRead( input_thread_t * p_input,
     p_netlist = ( netlist_t * ) p_input->p_method_data;
 
     /* Get an iovec pointer */
-    if( ( p_vec = input_NetlistGetiovec( p_netlist, &p_data ) ) == NULL )
+    if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL )
     {
         intf_ErrMsg( "DVD: read error" );
         return -1;
@@ -498,7 +498,7 @@ static int DVDRead( input_thread_t * p_input,
 #endif
 
     /* Update netlist indexes */
-    input_NetlistMviovec( p_netlist, p_method->i_read_once );
+    input_NetlistMviovec( p_netlist, p_method->i_read_once, &p_data );
 
     i_packet = 0;
     /* Read headers to compute payload length */
index 26aa41c690635510d1960a998cacc2fb1a1ff2f9..71681617817a2966b88915a7567502ee45e0772b 100644 (file)
@@ -2,7 +2,7 @@
  * input_ts.c: TS demux and netlist management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input_ts.c,v 1.1 2001/02/08 04:43:27 sam Exp $
+ * $Id: input_ts.c,v 1.2 2001/02/14 15:58:29 henri Exp $
  *
  * Authors: 
  *
@@ -29,6 +29,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <sys/uio.h>
+
 
 #include "config.h"
 #include "common.h"
@@ -44,6 +46,7 @@
 #include "input_ext-dec.h"
 
 #include "input.h"
+#include "input_ts.h"
 
 #include "mpeg_system.h"
 #include "input_netlist.h"
@@ -91,7 +94,7 @@ static int TSProbe( probedata_t * p_data )
     }
 
     /* verify that the first byte is 0x47 */
-    return 1;
+    return 0;
 }
 
 /*****************************************************************************
@@ -100,6 +103,58 @@ static int TSProbe( probedata_t * p_data )
 static void TSInit( input_thread_t * p_input )
 {
     /* Initialize netlist and TS structures */
+    thread_ts_data_t    * p_method;
+    pgrm_ts_data_t      * p_pgrm_demux;
+    es_descriptor_t     * kludge1;
+
+    /* Initialise structure */
+    p_method = malloc( sizeof( thread_ts_data_t ) );
+    if( p_method == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_input->b_error = 1;
+        return;
+    }
+    p_input->p_plugin_data = (void *)p_method;
+    p_input->p_method_data = NULL;
+    
+    /* XXX : For the time being, only file, after, i'll do the network */ 
+    
+    /* Initialize netlist */
+    if( input_NetlistInit( p_input, NB_DATA, NB_PES, TS_PACKET_SIZE, 
+                INPUT_READ_ONCE ) )
+    {
+        intf_ErrMsg( "Could not initialize netlist" );
+        return;
+    }
+   
+    /* Initialize the stream */
+    input_InitStream( p_input, sizeof( stream_ts_data_t ) );
+
+    /* FIXME : PSIDemux and PSIDecode */
+    /* Add audio and video programs */
+    /* p_input->stream.pp_programs[0] = */
+    input_AddProgram( p_input, 0, sizeof( pgrm_ts_data_t ) );
+    p_pgrm_demux = 
+        (pgrm_ts_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
+    p_pgrm_demux->i_pcr_pid = 0x78;
+
+    kludge1 = input_AddES( p_input, p_input->stream.pp_programs[0], 
+                           0x78, sizeof( es_ts_data_t ) );
+
+    // kludge
+    kludge1->i_type = MPEG2_VIDEO_ES;
+
+    input_SelectES( p_input, kludge1 );
+
+    vlc_mutex_lock( &(p_input->stream.stream_lock) );
+    p_input->stream.pp_programs[0]->b_is_ok = 1;
+    vlc_mutex_unlock( &(p_input->stream.stream_lock) );
+
+//debug
+intf_ErrMsg("End of TSINIT");    
 }
 
 /*****************************************************************************
@@ -119,6 +174,34 @@ static void TSEnd( input_thread_t * p_input )
 static int TSRead( input_thread_t * p_input,
                    data_packet_t * pp_packets[INPUT_READ_ONCE] )
 {
-    return -1;
-}
+    unsigned int i_read, i_loop;
+    struct iovec * p_iovec;
+    
+    memset( pp_packets, 0, INPUT_READ_ONCE*sizeof(data_packet_t *) );
+    
+    p_iovec = input_NetlistGetiovec( p_input->p_method_data );
+    
+    if ( p_iovec == NULL )
+    {
+        return( -1 ); /* empty netlist */
+    } 
+
+    i_read = readv( p_input->i_handle, p_iovec, INPUT_READ_ONCE );
+    
+    if( i_read == -1 )
+    {
+        intf_ErrMsg( "Could not readv" );
+        return( -1 );
+    }
+
+    input_NetlistMviovec( p_input->p_method_data, 
+            (int)(i_read/TS_PACKET_SIZE) , pp_packets );
 
+    /* check correct TS header */
+    for( i_loop=0; i_loop < (int)(i_read/TS_PACKET_SIZE); i_loop++ )
+    {
+        if( pp_packets[i_loop]->p_buffer[0] != 0x47 )
+            intf_ErrMsg( "Bad TS Packet (starcode != 0x47)." );
+    }
+    return 0;
+}
diff --git a/plugins/mpeg/input_ts.h b/plugins/mpeg/input_ts.h
new file mode 100644 (file)
index 0000000..f45d229
--- /dev/null
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * input.h: structures of the input not exported to other modules
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: input_ts.h,v 1.1 2001/02/14 15:58:29 henri 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.
+ *****************************************************************************/
+
+
+// #define NB_DATA 16384 
+// #define NB_PES  8192
+#define NB_DATA 17000
+#define NB_PES  9000
+
+
+typedef struct thread_ts_data_s { 
+    
+    // FILE *                  stream;
+    
+} thread_ts_data_t;
index b3593dc112e2eaed76744b16c2bcdd341b8fdcaa..884377f2c041f9d48ab72f410dc41d03529e0e4b 100644 (file)
@@ -2,7 +2,7 @@
  * input_netlist.c: netlist management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input_netlist.c,v 1.30 2001/02/08 17:44:12 massiot Exp $
+ * $Id: input_netlist.c,v 1.31 2001/02/14 15:58:29 henri Exp $
  *
  * Authors: Henri Fallon <henri@videolan.org>
  *
@@ -41,8 +41,8 @@
 #include "input_ext-intf.h"
 #include "input_ext-dec.h"
 
-#include "input_netlist.h"
 #include "input.h"
+#include "input_netlist.h"
 
 /*****************************************************************************
  * Local prototypes
@@ -67,6 +67,8 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes,
     
     p_netlist = (netlist_t *) p_input->p_method_data;
     
+    p_netlist->i_read_once = i_read_once;
+    
     /* allocate the buffers */ 
     p_netlist->p_buffers = 
         (byte_t *) malloc(i_buffer_size* i_nb_data );
@@ -107,7 +109,7 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes,
     }
     
     p_netlist->p_free_iovec = ( struct iovec * )
-        malloc( (i_nb_data + INPUT_READ_ONCE) * sizeof(struct iovec) );
+        malloc( (i_nb_data + p_netlist->i_read_once) * sizeof(struct iovec) );
     if ( p_netlist->p_free_iovec == NULL )
     {
         intf_ErrMsg ("Unable to malloc in netlist initialization (6)");
@@ -121,6 +123,9 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes,
 
         p_netlist->pp_free_data[i_loop]->p_buffer = 
             p_netlist->p_buffers + i_loop * i_buffer_size;
+      
+        p_netlist->pp_free_data[i_loop]->p_payload_start = 
+            p_netlist->pp_free_data[i_loop]->p_buffer;
         
         p_netlist->pp_free_data[i_loop]->p_payload_end =
             p_netlist->pp_free_data[i_loop]->p_buffer + i_buffer_size;
@@ -140,7 +145,7 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes,
    
         p_netlist->p_free_iovec[i_loop].iov_len = i_buffer_size;
     }
-    
+   
     /* vlc_mutex_init */
     vlc_mutex_init (&p_netlist->lock);
     
@@ -155,16 +160,17 @@ int input_NetlistInit( input_thread_t * p_input, int i_nb_data, int i_nb_pes,
     p_netlist->i_nb_pes = i_nb_pes;
     p_netlist->i_buffer_size = i_buffer_size;
 
-    p_netlist->i_read_once = i_read_once;
-
     return (0); /* Everything went all right */
 }
 
 /*****************************************************************************
  * input_NetlistGetiovec: returns an iovec pointer for a readv() operation
+ *****************************************************************************
+ * We return an iovec vector, so that readv can read many packets at a time,
+ * and we set pp_data to direct to the fifo pointer, which will allow us
+ * to get the corresponding data_packet.
  *****************************************************************************/
-struct iovec * input_NetlistGetiovec( void * p_method_data,
-                                      struct data_packet_s ** pp_data )
+struct iovec * input_NetlistGetiovec( void * p_method_data )
 {
     netlist_t * p_netlist;
 
@@ -191,22 +197,11 @@ struct iovec * input_NetlistGetiovec( void * p_method_data,
                 p_netlist->p_free_iovec, 
                 (p_netlist->i_read_once-
                     (p_netlist->i_nb_data-p_netlist->i_data_start))
-                    * sizeof(struct iovec*)
+                    * sizeof(struct iovec)
               );
 
     }
  
-    /* Gives a pointer to the data_packet struct associated with io_vec */
-    *pp_data = p_netlist->pp_free_data[p_netlist->i_data_start];
-
-    /* Initialize payload start and end */
-    p_netlist->pp_free_data[p_netlist->i_data_start]->p_payload_start 
-        = p_netlist->pp_free_data[p_netlist->i_data_start]->p_buffer;
-    p_netlist->pp_free_data[p_netlist->i_data_start]->p_payload_end 
-        = p_netlist->pp_free_data[p_netlist->i_data_start]->p_payload_start
-        + p_netlist->i_buffer_size;
-
     return &p_netlist->p_free_iovec[p_netlist->i_data_start];
 
 }
@@ -214,16 +209,34 @@ struct iovec * input_NetlistGetiovec( void * p_method_data,
 /*****************************************************************************
  * input_NetlistMviovec: move the iovec pointer after a readv() operation
  *****************************************************************************/
-void input_NetlistMviovec( void * p_method_data, size_t i_nb_iovec )
+void input_NetlistMviovec( void * p_method_data, size_t i_nb_iovec,
+                           struct data_packet_s * pp_packets[INPUT_READ_ONCE] )
 {
     netlist_t * p_netlist;
+    unsigned int i_loop = 0;
+    unsigned int i_current;
 
     /* cast */
     p_netlist = (netlist_t *) p_method_data;
     
     /* lock */
     vlc_mutex_lock ( &p_netlist->lock );
-    
+
+    i_current = p_netlist->i_data_start;
+
+
+    /* Fills a table of pointers to packets associated with the io_vec's */
+while (i_loop < i_nb_iovec )
+    {
+        if( i_current >= p_netlist->i_nb_data ) 
+            i_current-=p_netlist->i_nb_data;
+        
+        pp_packets[i_loop] = p_netlist->pp_free_data[i_current];
+
+        i_loop ++;
+        i_current ++;
+    }
+
     p_netlist->i_data_start += i_nb_iovec;
     p_netlist->i_data_start %= p_netlist->i_nb_data;
 
@@ -333,13 +346,18 @@ void input_NetlistDeletePacket( void * p_method_data, data_packet_t * p_data )
     /* lock */
     vlc_mutex_lock ( &p_netlist->lock );
 
-    /* Delete data_packet */
+
+   /* Delete data_packet */
     p_netlist->i_data_end ++;
     p_netlist->i_data_end %= p_netlist->i_nb_data;
-    p_netlist->pp_free_data[p_netlist->i_data_end] = p_data;
     
+    p_netlist->pp_free_data[p_netlist->i_data_end] = p_data;
     p_netlist->p_free_iovec[p_netlist->i_data_end].iov_base = p_data->p_buffer;
-    
+
+    /* re initialize for next time */
+    p_data->p_payload_start = p_data->p_buffer;
+    p_data->p_next = NULL;
     /* unlock */
     vlc_mutex_unlock (&p_netlist->lock);
 }
@@ -350,7 +368,7 @@ void input_NetlistDeletePacket( void * p_method_data, data_packet_t * p_data )
 void input_NetlistDeletePES( void * p_method_data, pes_packet_t * p_pes )
 {
     netlist_t * p_netlist; 
-    data_packet_t * p_current_packet;
+    data_packet_t * p_current_packet,* p_next_packet;
     
     /* cast */
     p_netlist = (netlist_t *)p_method_data;
@@ -366,12 +384,18 @@ void input_NetlistDeletePES( void * p_method_data, pes_packet_t * p_pes )
 
         p_netlist->i_data_end ++;
         p_netlist->i_data_end %= p_netlist->i_nb_data;
-        p_netlist->pp_free_data[p_netlist->i_data_end] = p_current_packet;
+
+        /* re initialize*/
+        p_current_packet->p_payload_start = p_current_packet->p_buffer;
         
+        p_netlist->pp_free_data[p_netlist->i_data_end] = p_current_packet;
+
         p_netlist->p_free_iovec[p_netlist->i_data_end].iov_base 
             = p_current_packet->p_buffer;
     
-        p_current_packet = p_current_packet->p_next;
+        p_next_packet = p_current_packet->p_next;
+        p_current_packet->p_next = NULL;
+        p_current_packet = p_next_packet;
     }
  
     /* delete our current PES packet */
index 49dae60cae0d9e606c621e1142046df52f96c8eb..099f74c9dbb1732a4f6073c2b41aeb792b77a1e5 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.35 2001/02/12 07:52:40 sam Exp $
+ * $Id: mpeg_system.c,v 1.36 2001/02/14 15:58:29 henri Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -448,7 +448,7 @@ void input_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
@@ -456,11 +456,12 @@ void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data,
             {
                 p_es->i_pes_real_size =
                                 U16_AT(p_data->p_payload_start + 4) + 6;
+                
             }
             else
-            {
+            { 
                 p_es->i_pes_real_size = 0;
-            }
+            } 
         }
         else
         {
@@ -864,7 +865,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
     }
 }
 
-
 /*
  * TS Demultiplexing
  */
@@ -884,7 +885,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
     es_ts_data_t *      p_es_demux = NULL;
     pgrm_ts_data_t *    p_pgrm_demux = NULL;
 
-#define p (p_data->p_buffer)
+    #define p (p_data->p_buffer)
 
     //intf_DbgMsg("input debug: TS-demultiplexing packet %p, pid %d",
     //            p_ts_packet, U16_AT(&p[1]) & 0x1fff);
@@ -897,8 +898,22 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
 
     /* Find out the elementary stream. */
     vlc_mutex_lock( &p_input->stream.stream_lock );
-    p_es = input_FindES( p_input, i_pid );
 
+// kludge    
+if ( i_pid == 0x78 )
+{
+    p_es = input_FindES( p_input, 0x78 );
+    p_es->i_type = MPEG2_VIDEO_ES;
+    if( p_es->p_pes == NULL )
+      intf_ErrMsg("Got p_es . p_es->p_pes == null ? %d",p_es->p_pes == NULL);
+}
+else
+{
+    p_es = NULL;
+    b_trash = 1;
+}
+
+    
     vlc_mutex_lock( &p_input->stream.control.control_lock );
     if( p_es == NULL || p_es->p_decoder_fifo == NULL
          || (p_es->b_audio && p_input->stream.control.b_mute) )
@@ -909,6 +924,15 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
     vlc_mutex_unlock( &p_input->stream.control.control_lock );
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
+// kludge
+    if (p_es != NULL )
+    {
+    
+    p_es_demux = (es_ts_data_t *)p_es->p_demux_data;
+    p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data; 
+    
+    p_pgrm_demux->i_pcr_pid = 0x78;
+
     if( (p_es->p_decoder_fifo != NULL) || (p_pgrm_demux->i_pcr_pid == i_pid) )
     {
 #ifdef STATS
@@ -916,6 +940,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
 #endif
 
         /* Extract adaptation field information if any */
+
         if( !b_adaptation )
         {
             /* We don't have any adaptation_field, so payload starts
@@ -973,6 +998,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
     
                     /* If this is a PCR_PID, and this TS packet contains a
                      * PCR, we pass it along to the PCR decoder. */
+
                     if( (p_pgrm_demux->i_pcr_pid == i_pid) && (p[5] & 0x10) )
                     {
                         /* There should be a PCR field in the packet, check
@@ -993,13 +1019,12 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
                 } /* 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 )
         {
             /* Everything is ok, just increase our counter */
-            p_es_demux->i_continuity_counter++;
+            (p_es_demux->i_continuity_counter)++;
         }
         else
         {
@@ -1046,10 +1071,13 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
         } /* continuity */
     } /* if selected or PCR */
 
+    }
+    
     /* Trash the packet if it has no payload or if it isn't selected */
     if( b_trash )
     {
-        p_input->pf_delete_packet( p_input, p_data );
+        
+        p_input->pf_delete_packet( p_input->p_method_data, p_data );
 #ifdef STATS
         p_input->c_packets_trashed++;
 #endif
@@ -1058,6 +1086,8 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
     {
         if( p_es_demux->b_psi )
         {
+//debug
+//printf("DemuxTS : Was a PSI\n");
             /* The payload contains PSI tables */
 #if 0
             /* FIXME ! write the PSI decoder :p */
@@ -1068,10 +1098,10 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
         else
         {
             /* The payload carries a PES stream */
-            if( b_unit_start )
-            input_GatherPES( p_input, p_data, p_es, b_unit_start, b_lost );
+            input_GatherPES( p_input, p_data, p_es, b_unit_start, b_lost ); 
         }
     }
 
 #undef p
+
 }