]> git.sesse.net Git - vlc/commitdiff
Next Generation Buffer Manager, for TS plug-in. Please test in-ten-si-vely !
authorChristophe Massiot <massiot@videolan.org>
Wed, 12 Dec 2001 13:48:09 +0000 (13:48 +0000)
committerChristophe Massiot <massiot@videolan.org>
Wed, 12 Dec 2001 13:48:09 +0000 (13:48 +0000)
include/input_ext-dec.h
include/input_ext-intf.h
include/input_ext-plugins.h
plugins/mpeg_system/input_ps.c
plugins/mpeg_system/input_ts.c
src/input/mpeg_system.c

index ae867f7e54ac76cf6f36ec49a5daff8044565f74..a9964df8bc8bbd4fdacd20ac85a8e62181c7906f 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-dec.h: structures exported to the VideoLAN decoders
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-dec.h,v 1.43 2001/12/12 11:18:38 massiot Exp $
+ * $Id: input_ext-dec.h,v 1.44 2001/12/12 13:48:09 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Kaempf <maxx@via.ecp.fr>
@@ -84,6 +84,9 @@ typedef struct pes_packet_s
        p_next fields of the data_packet_t struct) */
     data_packet_t *         p_first;      /* The first packet contained by this
                                            * PES (used by decoders). */
+    data_packet_t *         p_last;    /* The last packet contained by this
+                                          PES (used by the buffer allocator) */
+    int                     i_nb_data;
 
     /* Chained list used by the input buffers manager */
     struct pes_packet_s *   p_next;
index 5b9cd0ef9d8e2d62d52d71ab8be309bee8bf3ea1..eb991d6b7864e79a4fa2452a44f2d04174ac2ee6 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.52 2001/12/10 04:53:10 sam Exp $
+ * $Id: input_ext-intf.h,v 1.53 2001/12/12 13:48:09 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -66,7 +66,6 @@ typedef struct es_descriptor_s
 
     /* PES parser information */
     struct pes_packet_s *   p_pes;                            /* Current PES */
-    struct data_packet_s *  p_last;   /* The last packet gathered at present */
     int                     i_pes_real_size;   /* as indicated by the header */
 
     /* Decoder information */
index 5eb3e3a074a692dd8a727c8d0cacbb372a99aa7a..59e88cfc02b8d2949f54d13f52bfe58024e83a4f 100644 (file)
@@ -3,7 +3,7 @@
  *                      but exported to plug-ins
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: input_ext-plugins.h,v 1.9 2001/12/12 11:18:38 massiot Exp $
+ * $Id: input_ext-plugins.h,v 1.10 2001/12/12 13:48:09 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -114,8 +114,9 @@ static __inline__ void input_NullPacket( input_thread_t * p_input,
     if( p_pes != NULL )
     {
         p_pes->b_discontinuity = 1;
-        p_es->p_last->p_next = p_pad_data;
-        p_es->p_last = p_pad_data;
+        p_pes->p_last->p_next = p_pad_data;
+        p_pes->p_last = p_pad_data;
+        p_pes->i_nb_data++;
     }
     else
     {
@@ -127,7 +128,8 @@ static __inline__ void input_NullPacket( input_thread_t * p_input,
         }
 
         p_pes->i_rate = p_input->stream.control.i_rate;
-        p_pes->p_first = p_pad_data;
+        p_pes->p_first = p_pes->p_last = p_pad_data;
+        p_pes->i_nb_data = 1;
         p_pes->b_discontinuity = 1;
         input_DecodePES( p_es->p_decoder_fifo, p_pes );
     }
@@ -212,7 +214,7 @@ void                    input_NetlistEnd( struct input_thread_s * );
 /* Flags */
 #define BUFFERS_NOFLAGS         0
 #define BUFFERS_SHARED          1
-#define BUFFERS_UNIQUE_SIZE     2
+#define BUFFERS_UNIQUE_SIZE     2 /* Only with NB_LIFO == 1 */
 
 /*****************************************************************************
  * input_buffers_t: defines a LIFO per data type to keep
@@ -295,6 +297,8 @@ static void input_BuffersEnd( void * _p_buffers )                           \
         if( p_main->b_stats )                                               \
         {                                                                   \
             int i;                                                          \
+            intf_StatMsg( "input buffers stats: pes: %d packets",           \
+                          p_buffers->pes.i_depth );                         \
             for( i = 0; i < NB_LIFO; i++ )                                  \
             {                                                               \
                 intf_StatMsg(                                               \
@@ -343,21 +347,14 @@ static void input_BuffersEnd( void * _p_buffers )                           \
  * input_NewPacket: return a pointer to a data packet of the appropriate size
  *****************************************************************************/
 #define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO )                         \
-static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size )  \
+static __inline__ data_packet_t * _input_NewPacket( void * _p_buffers,      \
+                                                    size_t i_size )         \
 {                                                                           \
     input_buffers_t *   p_buffers = (input_buffers_t *)_p_buffers;          \
     int                 i_select;                                           \
     data_packet_t *     p_data;                                             \
                                                                             \
-    /* Safety checks */                                                     \
-    if( i_size > INPUT_MAX_PACKET_SIZE )                                    \
-    {                                                                       \
-        intf_ErrMsg( "Packet too big (%d)", i_size );                       \
-        return NULL;                                                        \
-    }                                                                       \
-                                                                            \
-    vlc_mutex_lock( &p_buffers->lock );                                     \
-                                                                            \
+    /* Safety check */                                                      \
     if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION )                     \
     {                                                                       \
         vlc_mutex_unlock( &p_buffers->lock );                               \
@@ -383,8 +380,9 @@ static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size )  \
         p_buffers->data[i_select].i_depth--;                                \
                                                                             \
         /* Reallocate the packet if it is too small or too large */         \
-        if( p_data->p_buffer_end - p_data->p_buffer < i_size ||             \
-            p_data->p_buffer_end - p_data->p_buffer > 3 * i_size )          \
+        if( !(FLAGS & BUFFERS_UNIQUE_SIZE) &&                               \
+            (p_data->p_buffer_end - p_data->p_buffer < i_size ||            \
+             p_data->p_buffer_end - p_data->p_buffer > 3 * i_size) )        \
         {                                                                   \
             p_buffers->i_allocated -= p_data->p_buffer_end                  \
                                         - p_data->p_buffer;                 \
@@ -415,8 +413,6 @@ static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size )  \
         p_buffers->i_allocated += i_size;                                   \
     }                                                                       \
                                                                             \
-    vlc_mutex_unlock( &p_buffers->lock );                                   \
-                                                                            \
     /* Initialize data */                                                   \
     p_data->p_next = NULL;                                                  \
     p_data->b_discard_payload = 0;                                          \
@@ -424,6 +420,24 @@ static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size )  \
     p_data->p_payload_end = p_data->p_buffer + i_size;                      \
                                                                             \
     return( p_data );                                                       \
+}                                                                           \
+                                                                            \
+static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size )  \
+{                                                                           \
+    input_buffers_t *   p_buffers = (input_buffers_t *)_p_buffers;          \
+    data_packet_t *     p_data;                                             \
+                                                                            \
+    /* Safety check */                                                      \
+    if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && i_size > INPUT_MAX_PACKET_SIZE )  \
+    {                                                                       \
+        intf_ErrMsg( "Packet too big (%d)", i_size );                       \
+        return NULL;                                                        \
+    }                                                                       \
+                                                                            \
+    vlc_mutex_lock( &p_buffers->lock );                                     \
+    p_data = _input_NewPacket( _p_buffers, i_size );                        \
+    vlc_mutex_unlock( &p_buffers->lock );                                   \
+    return( p_data );                                                       \
 }
 
 /*****************************************************************************
@@ -453,11 +467,14 @@ static __inline__ void _input_DeletePacket( void * _p_buffers,              \
         p_buffers->data[i_select].p_stack = p_data;                         \
         p_buffers->data[i_select].i_depth++;                                \
                                                                             \
-        /* Update Bresenham mean (very approximative) */                    \
-        p_buffers->data[i_select].i_average_size = ( i_size                 \
-            + p_buffers->data[i_select].i_average_size                      \
-              * (INPUT_BRESENHAM_NB - 1) )                                  \
-            / INPUT_BRESENHAM_NB;                                           \
+        if( !(FLAGS & BUFFERS_UNIQUE_SIZE) )                                \
+        {                                                                   \
+            /* Update Bresenham mean (very approximative) */                \
+            p_buffers->data[i_select].i_average_size = ( i_size             \
+                 + p_buffers->data[i_select].i_average_size                 \
+                   * (INPUT_BRESENHAM_NB - 1) )                             \
+                 / INPUT_BRESENHAM_NB;                                      \
+        }                                                                   \
     }                                                                       \
     else                                                                    \
     {                                                                       \
@@ -510,7 +527,8 @@ static pes_packet_t * input_NewPES( void * _p_buffers )                     \
     p_pes->b_data_alignment = p_pes->b_discontinuity =                      \
         p_pes->i_pts = p_pes->i_dts = 0;                                    \
     p_pes->i_pes_size = 0;                                                  \
-    p_pes->p_first = NULL;                                                  \
+    p_pes->p_first = p_pes->p_last = NULL;                                  \
+    p_pes->i_nb_data = 0;                                                   \
                                                                             \
     return( p_pes );                                                        \
 }
@@ -518,20 +536,33 @@ static pes_packet_t * input_NewPES( void * _p_buffers )                     \
 /*****************************************************************************
  * input_DeletePES: put a pes and all data packets back into the cache
  *****************************************************************************/
-#define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, PES_CACHE_SIZE )         \
+#define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, DATA_CACHE_SIZE,         \
+                                   PES_CACHE_SIZE )                         \
 static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes )      \
 {                                                                           \
     input_buffers_t *   p_buffers = (input_buffers_t *)_p_buffers;          \
-    data_packet_t *     p_data;                                             \
                                                                             \
     vlc_mutex_lock( &p_buffers->lock );                                     \
                                                                             \
-    p_data = p_pes->p_first;                                                \
-    while( p_data != NULL )                                                 \
+    if( !(FLAGS & BUFFERS_UNIQUE_SIZE)                                      \
+            || p_buffers->data[0].i_depth > DATA_CACHE_SIZE )               \
+          /* This is a little inaccurate but who cares if we have too many  \
+           * packets in the cache ? */                                      \
     {                                                                       \
-        data_packet_t * p_next = p_data->p_next;                            \
-        _input_DeletePacket( _p_buffers, p_data );                          \
-        p_data = p_next;                                                    \
+        data_packet_t *     p_data = p_pes->p_first;                        \
+        while( p_data != NULL )                                             \
+        {                                                                   \
+            data_packet_t * p_next = p_data->p_next;                        \
+            _input_DeletePacket( _p_buffers, p_data );                      \
+            p_data = p_next;                                                \
+        }                                                                   \
+    }                                                                       \
+    else                                                                    \
+    {                                                                       \
+        /* NB_LIFO == 1 and we can keep all data packets */                 \
+        p_pes->p_last->p_next = p_buffers->data[0].p_stack;                 \
+        p_buffers->data[0].p_stack = p_pes->p_first;                        \
+        p_buffers->data[0].i_depth += p_pes->i_nb_data;                     \
     }                                                                       \
                                                                             \
     if( p_buffers->pes.i_depth < PES_CACHE_SIZE )                           \
@@ -549,6 +580,45 @@ static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes )      \
     vlc_mutex_unlock( &p_buffers->lock );                                   \
 }
 
+/*****************************************************************************
+ * input_BuffersToIO: return an io vector (only with BUFFERS_UNIQUE_SIZE)
+ *****************************************************************************/
+#define DECLARE_BUFFERS_TOIO( FLAGS, BUFFER_SIZE )                          \
+static data_packet_t * input_BuffersToIO( void * _p_buffers,                \
+                                         struct iovec * p_iovec, int i_nb ) \
+{                                                                           \
+    input_buffers_t *   p_buffers = (input_buffers_t *)_p_buffers;          \
+    data_packet_t *     p_data = NULL;                                      \
+    int                 i;                                                  \
+                                                                            \
+    vlc_mutex_lock( &p_buffers->lock );                                     \
+                                                                            \
+    for( i = i_nb - 1; i >= 0; i-- )                                        \
+    {                                                                       \
+        data_packet_t * p_next = _input_NewPacket( _p_buffers,              \
+                                          BUFFER_SIZE /* UNIQUE_SIZE */ );  \
+        if( p_next == NULL )                                                \
+        {                                                                   \
+            while( p_data != NULL )                                         \
+            {                                                               \
+                p_next = p_data->p_next;                                    \
+                _input_DeletePacket( _p_buffers, p_data );                  \
+                p_data = p_next;                                            \
+            }                                                               \
+            return( NULL );                                                 \
+        }                                                                   \
+                                                                            \
+        p_iovec[i].iov_base = p_next->p_payload_start;                      \
+        p_iovec[i].iov_len = BUFFER_SIZE;                                   \
+        p_next->p_next = p_data;                                            \
+        p_data = p_next;                                                    \
+    }                                                                       \
+                                                                            \
+    vlc_mutex_unlock( &p_buffers->lock );                                     \
+                                                                            \
+    return( p_data );                                                       \
+}
+
 
 /*
  * Optional MPEG demultiplexing
index 242b9c3818acf471a8f7429dfbd1c456a7778f13..388c951f0133bc87e381ced12bc6f40a11f6cc5c 100644 (file)
@@ -2,7 +2,7 @@
  * input_ps.c: PS demux and packet management
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: input_ps.c,v 1.3 2001/12/12 11:18:38 massiot Exp $
+ * $Id: input_ps.c,v 1.4 2001/12/12 13:48:09 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Cyril Deguet <asmax@via.ecp.fr>
@@ -103,7 +103,7 @@ DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
 DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
 DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
 DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
-DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
+DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150, 150 );
 
 
 /*****************************************************************************
index 21f9b0d49cfc9841f970daebfa5d93eee08e1550..0d7cea490ab4f0621bb058cda0f69142815db350 100644 (file)
@@ -2,7 +2,7 @@
  * input_ts.c: TS demux and netlist management
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: input_ts.c,v 1.2 2001/12/10 04:53:11 sam Exp $
+ * $Id: input_ts.c,v 1.3 2001/12/12 13:48:09 massiot Exp $
  *
  * Authors: Henri Fallon <henri@videolan.org>
  *
@@ -91,6 +91,20 @@ static void TSEnd       ( struct input_thread_s * );
 static int  TSRead      ( struct input_thread_s *,
                           data_packet_t * p_packets[INPUT_READ_ONCE] );
 
+/*****************************************************************************
+ * Declare a buffer manager
+ *****************************************************************************/
+#define FLAGS           BUFFERS_UNIQUE_SIZE
+#define NB_LIFO         1
+DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
+DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
+DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
+DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
+DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 1000 );
+DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
+DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 1000, 150 );
+DECLARE_BUFFERS_TOIO( FLAGS, TS_PACKET_SIZE );
+
 /*****************************************************************************
  * Functions exported as capabilities. They are declared as static so that
  * we don't pollute the namespace too much.
@@ -108,10 +122,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
     input.pf_set_program      = input_SetProgram;
     input.pf_read             = TSRead;
     input.pf_demux            = input_DemuxTS;
-    input.pf_new_packet       = input_NetlistNewPacket;
-    input.pf_new_pes          = input_NetlistNewPES;
-    input.pf_delete_packet    = input_NetlistDeletePacket;
-    input.pf_delete_pes       = input_NetlistDeletePES;
+    input.pf_new_packet       = input_NewPacket;
+    input.pf_new_pes          = input_NewPES;
+    input.pf_delete_packet    = input_DeletePacket;
+    input.pf_delete_pes       = input_DeletePES;
     input.pf_rewind           = NULL;
     input.pf_seek             = NULL;
 #undef input
@@ -160,7 +174,6 @@ 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;
     es_descriptor_t     * p_pat_es;
     es_ts_data_t        * p_demux_data;
@@ -184,11 +197,9 @@ static void TSInit( input_thread_t * p_input )
     p_input->p_method_data = NULL;
 
 
-    /* Initialize netlist */
-    if( input_NetlistInit( p_input, NB_DATA, NB_DATA, NB_PES, TS_PACKET_SIZE,
-                INPUT_READ_ONCE ) )
+    if( (p_input->p_method_data = input_BuffersInit()) == NULL )
     {
-        intf_ErrMsg( "TS input : Could not initialize netlist" );
+        p_input->b_error = 1;
         return;
     }
 
@@ -227,7 +238,7 @@ static void TSEnd( input_thread_t * p_input )
         input_DelES( p_input, p_pat_es );
 
     free(p_input->p_plugin_data);
-    input_NetlistEnd( p_input );
+    input_BuffersEnd( p_input->p_method_data );
 }
 
 /*****************************************************************************
@@ -243,7 +254,8 @@ static int TSRead( input_thread_t * p_input,
     unsigned int    i_loop;
     int             i_read;
     int             i_data = 1;
-    struct iovec  * p_iovec;
+    struct iovec    p_iovec[INPUT_READ_ONCE];
+    data_packet_t * p_data;
     struct timeval  timeout;
 
     /* Init */
@@ -278,11 +290,12 @@ static int TSRead( input_thread_t * p_input,
     if( i_data )
     {
         /* Get iovecs */
-        p_iovec = input_NetlistGetiovec( p_input->p_method_data );
+        p_data = input_BuffersToIO( p_input->p_method_data, p_iovec,
+                                    INPUT_READ_ONCE );
 
         if ( p_iovec == NULL )
         {
-            return( -1 ); /* empty netlist */
+            return( -1 );
         }
 
 #if defined( WIN32 )
@@ -306,24 +319,13 @@ static int TSRead( input_thread_t * p_input,
             i_read = 0;
         }
 #endif
-        if( i_read == -1 )
-        {
-            intf_ErrMsg( "input error: TS readv error" );
-            return( -1 );
-        }
-
-        /* EOF */
-        if( i_read == 0 && p_input->stream.b_seekable )
-        {
-            return( 1 );
-        }
-
-        input_NetlistMviovec( p_input->p_method_data,
-                (int)(((i_read-1)/TS_PACKET_SIZE)+1) , pp_packets );
-
         /* check correct TS header */
         for( i_loop=0; i_loop * TS_PACKET_SIZE < i_read; i_loop++ )
         {
+            pp_packets[i_loop] = p_data;
+            p_data = p_data->p_next;
+            pp_packets[i_loop]->p_next = NULL;
+
             if( pp_packets[i_loop]->p_buffer[0] != 0x47 )
                 intf_ErrMsg( "input error: bad TS packet (starts with "
                              "0x%.2x, should be 0x47)",
@@ -331,9 +333,26 @@ static int TSRead( input_thread_t * p_input,
         }
         for( ; i_loop < INPUT_READ_ONCE ; i_loop++ )
         {
+            data_packet_t * p_next = p_data->p_next;
+            input_DeletePacket( p_input->p_method_data, p_data );
+            p_data = p_next;
             pp_packets[i_loop] = NULL;
         }
 
+        /* Error */
+        if( i_read == -1 )
+        {
+            intf_ErrMsg( "input error: TS readv error" );
+            return( -1 );
+        }
+
+        /* EOF */
+        if( i_read == 0 && p_input->stream.b_seekable )
+        {
+            return( 1 );
+        }
+
+
         p_input->stream.p_selected_area->i_tell += i_read;
     }
     return 0;
index 3f70399b8e8322c933889cfca8715ffbd8d7abda..8ada0da0dee0c0f1731396d87f17988f33b8321d 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.71 2001/12/11 13:55:55 massiot Exp $
+ * $Id: mpeg_system.c,v 1.72 2001/12/12 13:48:09 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -476,10 +476,11 @@ void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data,
         else
         {
             /* Update the relations between the data packets */
-            p_es->p_last->p_next = p_data;
+            p_pes->p_last->p_next = p_data;
         }
 
-        p_es->p_last = p_data;
+        p_pes->p_last = p_data;
+        p_pes->i_nb_data++;
 
         /* Size of the payload carried in the data packet */
         p_pes->i_pes_size += (p_data->p_payload_end