]> git.sesse.net Git - vlc/commitdiff
-New function for DVD reading, that is able to read multiple blocks
authorStéphane Borel <stef@videolan.org>
Fri, 2 Mar 2001 03:32:46 +0000 (03:32 +0000)
committerStéphane Borel <stef@videolan.org>
Fri, 2 Mar 2001 03:32:46 +0000 (03:32 +0000)
(I've chosen 32 now), that doesn't use any memcpy anymore and is also much
faster. It is ready now for cell positioning in multi-angle DVD (to come
soon).

-DVD specific netlist adapted to 2048 bytes long blocks that contain
several data_packets.

-Modification in mpeg_system.c to use p_payload_start instead of
p_buffer (necessary for DVD plugin). It does not break other plugins
since they set p_payload_start to p_buffer

-New field i_read_once in input_thread_s to be able to read more than
the TS related 7 packets ; i_read_once is set to INPUT_READ_ONCE by
defaults but plugins can change it during initialisation.

Please check that nothing is broken :)

Makefile.in
include/input_ext-dec.h
include/input_ext-intf.h
plugins/dvd/dvd_netlist.c [new file with mode: 0644]
plugins/dvd/dvd_netlist.h [new file with mode: 0644]
plugins/dvd/input_dvd.c
plugins/dvd/input_dvd.h
src/input/input.c
src/input/mpeg_system.c

index 546fa7845f08e8bea99e6fe4eadfcda1d1cc13d1..8abb706764cb4fb02e5af4d607452bf3bf45a697 100644 (file)
@@ -300,6 +300,7 @@ PLUGIN_DUMMY =      plugins/dummy/dummy.o \
 
 PLUGIN_DVD =   plugins/dvd/dvd.o \
                plugins/dvd/input_dvd.o \
+               plugins/dvd/dvd_netlist.o \
                plugins/dvd/dvd_ioctl.o \
                plugins/dvd/dvd_ifo.o \
                plugins/dvd/dvd_udf.o \
index 164629709771a0e4a80df731d474ae0981d9380f..85c3d5e5d6e3afbc7e9255d1b71436941baa6c35 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.22 2001/02/08 17:44:12 massiot Exp $
+ * $Id: input_ext-dec.h,v 1.23 2001/03/02 03:32:46 stef Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Kaempf <maxx@via.ecp.fr>
@@ -40,6 +40,8 @@ typedef struct data_packet_s
     byte_t *                p_payload_end;                    /* guess ? :-) */
     boolean_t               b_discard_payload;  /* is the packet messed up ? */
 
+    int *                   pi_refcount;
+
     /* Used to chain the TS packets that carry data for a same PES or PSI */
     struct data_packet_s *  p_next;
 } data_packet_t;
index 7a9b19ce77bc5f2060be53d3cd18926c391180a2..4925c440013c27512a6f760af808b9fe6b41fb86 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.26 2001/02/22 17:00:20 massiot Exp $
+ * $Id: input_ext-intf.h,v 1.27 2001/03/02 03:32:46 stef Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -278,6 +278,8 @@ typedef struct input_thread_s
     char *                  p_source;
 
     int                     i_handle;           /* socket or file descriptor */
+    int                     i_read_once;        /* number of packet read by
+                                                 * pf_read once */
     void *                  p_method_data;     /* data of the packet manager */
     void *                  p_plugin_data;             /* data of the plugin */
 
diff --git a/plugins/dvd/dvd_netlist.c b/plugins/dvd/dvd_netlist.c
new file mode 100644 (file)
index 0000000..a197015
--- /dev/null
@@ -0,0 +1,525 @@
+/*****************************************************************************
+ * dvd_netlist.c: Specific netlist for DVD packets
+ * ---
+ * The original is in src/input.
+ * There is only one major change from input_netlist.c : data is now a
+ * pointer to an offset in iovec ; and iovec has a reference counter. It
+ * will only be given back to netlist when refcount is zero.
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
+ * $Id: dvd_netlist.c,v 1.1 2001/03/02 03:32:46 stef Exp $
+ *
+ * Authors: Henri Fallon <henri@videolan.org>
+ *          Stéphane Borel <stef@videolan.org>
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/uio.h>                                         /* struct iovec */
+#include <unistd.h>
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"                                                /* mutex */
+#include "mtime.h"
+#include "intf_msg.h"                                           /* intf_*Msg */
+
+#include "stream_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
+
+#include "input.h"
+#include "dvd_netlist.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * DVDNetlistInit: allocates netlist buffers and init indexes
+ * ---
+ * Changes from input_NetList: we have to give the length of the buffer which
+ * is different from i_nb_data now, since we may have several data pointers
+ * in one iovec. Thus we can only delete an iovec when its refcount is 0.
+ * We only received a buffer with a GetIovec whereas NewPacket gives a pointer.
+ *
+ * Warning: i_nb_iovec, i_nb_data, i_nb_pes have to be 2^x
+ *****************************************************************************/
+int DVDNetlistInit( input_thread_t * p_input,
+                    int i_nb_iovec, int i_nb_data, int i_nb_pes,
+                    size_t i_buffer_size, int i_read_once )
+{
+    unsigned int i_loop;
+    netlist_t * p_netlist;
+
+    /* First we allocate and initialise our netlist struct */
+    p_input->p_method_data = malloc(sizeof(netlist_t));
+    if ( p_input->p_method_data == NULL )
+    {
+        intf_ErrMsg("Unable to malloc the DVD netlist struct");
+        return (-1);
+    }
+    
+    p_netlist = (netlist_t *) p_input->p_method_data;
+
+    /* Nb of packets read once by input */
+    p_netlist->i_read_once = i_read_once;
+    
+    /* allocate the buffers */ 
+    p_netlist->p_buffers = malloc( i_nb_iovec *i_buffer_size );
+    if ( p_netlist->p_buffers == NULL )
+    {
+        intf_ErrMsg ("Unable to malloc in DVD netlist initialization (1)");
+        return (-1);
+    }
+    
+    /* table of pointers to data packets */
+    p_netlist->p_data = malloc( i_nb_data *sizeof(data_packet_t) );
+    if ( p_netlist->p_data == NULL )
+    {
+        intf_ErrMsg ("Unable to malloc in DVD netlist initialization (2)");
+        return (-1);
+    }
+    
+    /* table of pointer to PES packets */
+    p_netlist->p_pes = malloc( i_nb_pes *sizeof(pes_packet_t) );
+    if ( p_netlist->p_pes == NULL )
+    {
+        intf_ErrMsg ("Unable to malloc in DVD netlist initialization (3)");
+        return (-1);
+    }
+    
+    /* allocate the FIFOs : tables of free pointers */
+    p_netlist->pp_free_data = 
+                        malloc( i_nb_data *sizeof(data_packet_t *) );
+    if ( p_netlist->pp_free_data == NULL )
+    {
+        intf_ErrMsg ("Unable to malloc in DVD netlist initialization (4)");
+    }
+    p_netlist->pp_free_pes = 
+                        malloc( i_nb_pes *sizeof(pes_packet_t *) );
+    if ( p_netlist->pp_free_pes == NULL )
+    {
+        intf_ErrMsg ("Unable to malloc in DVD netlist initialization (5)");
+    }
+    
+    p_netlist->p_free_iovec =
+        malloc( (i_nb_iovec + p_netlist->i_read_once) * sizeof(struct iovec) );
+    if ( p_netlist->p_free_iovec == NULL )
+    {
+        intf_ErrMsg ("Unable to malloc in DVD netlist initialization (6)");
+    }
+
+    /* table for reference counter of iovecs */
+    p_netlist->pi_refcount = malloc( i_nb_iovec *sizeof(int) );
+    if ( p_netlist->pi_refcount == NULL )
+    {
+        intf_ErrMsg ("Unable to malloc in DVD netlist initialization (7)");
+        return (-1);
+    }
+
+    /* Fill the data FIFO */
+    for ( i_loop = 0; i_loop < i_nb_data; i_loop++ )
+    {
+        p_netlist->pp_free_data[i_loop] = 
+            p_netlist->p_data + i_loop;
+    }
+
+    /* Fill the PES FIFO */
+    for ( i_loop = 0; i_loop < i_nb_pes ; i_loop++ )
+    {
+        p_netlist->pp_free_pes[i_loop] = 
+            p_netlist->p_pes + i_loop;
+    }
+   
+    /* Deal with the iovec */
+    for ( i_loop = 0; i_loop < i_nb_iovec; i_loop++ )
+    {
+        p_netlist->p_free_iovec[i_loop].iov_base = 
+            p_netlist->p_buffers + i_loop * i_buffer_size;
+   
+        p_netlist->p_free_iovec[i_loop].iov_len = i_buffer_size;
+    }
+
+    /* initialize reference counters */
+    memset( p_netlist->pi_refcount, 0, i_nb_iovec *sizeof(int) );
+   
+    /* vlc_mutex_init */
+    vlc_mutex_init (&p_netlist->lock);
+    
+    /* initialize indexes */
+    p_netlist->i_iovec_start = 0;
+    p_netlist->i_iovec_end = i_nb_iovec - 1;
+
+    p_netlist->i_data_start = 0;
+    p_netlist->i_data_end = i_nb_data - 1;
+
+    p_netlist->i_pes_start = 0;
+    p_netlist->i_pes_end = i_nb_pes - 1;
+
+    /* we give (nb - 1) to use & instead of %
+     * if you really need nb you have to add 1 */
+    p_netlist->i_nb_iovec = i_nb_iovec - 1;
+    p_netlist->i_nb_data = i_nb_data - 1;
+    p_netlist->i_nb_pes = i_nb_pes - 1;
+    p_netlist->i_buffer_size = i_buffer_size;
+
+    return (0); /* Everything went all right */
+}
+
+/*****************************************************************************
+ * DVDGetiovec: 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 * DVDGetiovec( void * p_method_data )
+{
+    netlist_t * p_netlist;
+
+    /* cast */
+    p_netlist = ( netlist_t * ) p_method_data;
+    
+    /* check */
+    if( (
+     (p_netlist->i_iovec_end - p_netlist->i_iovec_start)
+        & p_netlist->i_nb_iovec ) < p_netlist->i_read_once )
+    {
+        intf_ErrMsg("Empty iovec FIFO. Unable to allocate memory");
+        return (NULL);
+    }
+
+    /* readv only takes contiguous buffers 
+     * so, as a solution, we chose to have a FIFO a bit longer
+     * than i_nb_data, and copy the begining of the FIFO to its end
+     * if the readv needs to go after the end */
+    if( p_netlist->i_nb_iovec - p_netlist->i_iovec_start + 1 <
+                                                    p_netlist->i_read_once )
+    {
+        memcpy( &p_netlist->p_free_iovec[p_netlist->i_nb_iovec + 1], 
+                p_netlist->p_free_iovec, 
+                (p_netlist->i_read_once -
+                    (p_netlist->i_nb_iovec + 1 - p_netlist->i_iovec_start))
+                    * sizeof(struct iovec)
+              );
+
+    }
+
+    return p_netlist->p_free_iovec + p_netlist->i_iovec_start;
+
+}
+
+/*****************************************************************************
+ * DVDMviovec: move the iovec pointer by one after a readv() operation and
+ * gives a data_packet corresponding to iovec in p_data
+ *****************************************************************************/
+void DVDMviovec( void * p_method_data, int i_nb_iovec,
+                 struct data_packet_s ** pp_data )
+{
+    netlist_t * p_netlist;
+    unsigned int i_loop = 0;
+
+    /* cast */
+    p_netlist = (netlist_t *)p_method_data;
+    
+    /* lock */
+    vlc_mutex_lock( &p_netlist->lock );
+
+    /* Fills a table of pointers to packets associated with the io_vec's */
+    while( i_loop < i_nb_iovec )
+    {
+        pp_data[i_loop] = p_netlist->pp_free_data[p_netlist->i_data_start];
+        
+        pp_data[i_loop]->p_buffer =
+                    p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
+        
+        pp_data[i_loop]->pi_refcount = p_netlist->pi_refcount +
+                                       p_netlist->i_iovec_start;
+        p_netlist->i_iovec_start ++;
+        p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
+
+        p_netlist->i_data_start ++;
+        p_netlist->i_data_start &= p_netlist->i_nb_data;
+
+        i_loop ++;
+    }
+
+    /* unlock */
+    vlc_mutex_unlock( &p_netlist->lock );
+    
+}
+
+/*****************************************************************************
+ * DVDNewPtr: returns a free data_packet_t
+ * Gives a pointer ; its fields need to be initialized
+ *****************************************************************************/
+struct data_packet_s * DVDNewPtr( void * p_method_data )
+{    
+    netlist_t * p_netlist; 
+    struct data_packet_s * p_return;
+    
+    /* cast */
+    p_netlist = ( netlist_t * ) p_method_data; 
+
+#ifdef DEBUG
+    if( i_buffer_size > p_netlist->i_buffer_size )
+    {
+        /* This should not happen */
+        intf_ErrMsg( "Netlist packet too small !" );
+        return NULL;
+    }
+#endif
+
+    /* lock */
+    vlc_mutex_lock ( &p_netlist->lock );
+        
+    /* check */
+    if ( p_netlist->i_data_start == p_netlist->i_data_end )
+    {
+        intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
+        return ( NULL );
+    }
+    
+    p_return = (p_netlist->pp_free_data[p_netlist->i_data_start]);
+
+    p_netlist->i_data_start++;
+    p_netlist->i_data_start &= p_netlist->i_nb_data;
+
+    /* unlock */
+    vlc_mutex_unlock (&p_netlist->lock);
+
+    return ( p_return );
+}
+
+/*****************************************************************************
+ * DVDNewPacket: returns a free data_packet_t, and takes a corresponding
+ * storage iovec
+ *****************************************************************************/
+struct data_packet_s * DVDNewPacket( void * p_method_data,
+                                     size_t i_buffer_size )
+{
+    netlist_t *             p_netlist;
+    struct data_packet_s *  p_packet;
+
+    /* cast */
+    p_netlist = (netlist_t *)p_method_data;
+    
+    /* lock */
+    vlc_mutex_lock( &p_netlist->lock );
+
+     /* check */
+    if ( p_netlist->i_iovec_start == p_netlist->i_iovec_end )
+    {
+        intf_ErrMsg("Empty io_vec FIFO in netlist. Unable to allocate memory");
+        return ( NULL );
+    }
+
+    if ( p_netlist->i_data_start == p_netlist->i_data_end )
+    {
+        intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
+        return ( NULL );
+    }
+
+
+    /* Gives an io_vec and associated data */
+    p_packet = p_netlist->pp_free_data[p_netlist->i_data_start];
+        
+    p_packet->p_buffer =
+               p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
+        
+    p_packet->p_payload_start = p_packet->p_buffer;
+        
+    p_packet->p_payload_end =
+               p_packet->p_buffer + i_buffer_size;
+
+    p_packet->pi_refcount = p_netlist->pi_refcount + p_netlist->i_iovec_start;
+
+    p_netlist->i_iovec_start ++;
+    p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
+
+    p_netlist->i_data_start ++;
+    p_netlist->i_data_start &= p_netlist->i_nb_data;
+
+    /* unlock */
+    vlc_mutex_unlock( &p_netlist->lock );
+
+    return p_packet;
+}
+
+/*****************************************************************************
+ * DVDNewPES: returns a free pes_packet_t
+ *****************************************************************************/
+struct pes_packet_s * DVDNewPES( void * p_method_data )
+{
+    netlist_t * p_netlist;
+    pes_packet_t * p_return;
+    
+    /* cast */ 
+    p_netlist = (netlist_t *) p_method_data;
+    
+    /* lock */
+    vlc_mutex_lock ( &p_netlist->lock );
+    
+    /* check */
+    if ( p_netlist->i_pes_start == p_netlist->i_pes_end )
+    {
+        intf_ErrMsg("Empty PES FIFO in netlist - Unable to allocate memory");
+        return ( NULL );
+    }
+
+    /* allocate */
+    p_return = p_netlist->pp_free_pes[p_netlist->i_pes_start];
+    p_netlist->i_pes_start++;
+    p_netlist->i_pes_start &= p_netlist->i_nb_pes; 
+   
+    /* unlock */
+    vlc_mutex_unlock (&p_netlist->lock);
+    
+    /* initialize PES */
+    p_return->b_data_alignment = 
+        p_return->b_discontinuity = 
+        p_return->i_pts = p_return->i_dts = 0;
+    p_return->i_pes_size = 0;
+    p_return->p_first = NULL;
+   
+    return ( p_return );
+}
+
+/*****************************************************************************
+ * DVDDeletePacket: puts a data_packet_t back into the netlist
+ *****************************************************************************/
+void DVDDeletePacket( void * p_method_data, data_packet_t * p_data )
+{
+    netlist_t * p_netlist;
+    
+    /* cast */
+    p_netlist = (netlist_t *) p_method_data;
+
+    /* lock */
+    vlc_mutex_lock ( &p_netlist->lock );
+
+
+   /* 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;
+
+    /* Update reference counter */
+    (*p_data->pi_refcount)--;
+
+    if( (*p_data->pi_refcount) == 0 )
+    {
+
+        p_netlist->i_iovec_end++;
+        p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
+        p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
+                                                            p_data->p_buffer;
+    }
+
+    /* re initialize for next time */
+    p_data->p_next = NULL;
+    p_data->b_discard_payload = 0;
+    /* unlock */
+    vlc_mutex_unlock (&p_netlist->lock);
+}
+
+/*****************************************************************************
+ * DVDDeletePES: puts a pes_packet_t back into the netlist
+ *****************************************************************************/
+void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
+{
+    netlist_t * p_netlist; 
+    data_packet_t * p_current_packet,* p_next_packet;
+    
+    /* cast */
+    p_netlist = (netlist_t *)p_method_data;
+
+    /* lock */
+    vlc_mutex_lock ( &p_netlist->lock );
+
+    /* delete free  p_pes->p_first, p_next ... */
+    p_current_packet = p_pes->p_first;
+    while ( p_current_packet != NULL )
+    {
+        /* copy of NetListDeletePacket, duplicate code avoid many locks */
+
+        p_netlist->i_data_end ++;
+        p_netlist->i_data_end &= p_netlist->i_nb_data;
+
+        /* 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;
+
+        /* Update reference counter */
+        (*p_current_packet->pi_refcount)--;
+
+        if( (*p_current_packet->pi_refcount) == 0 )
+        {
+            p_netlist->i_iovec_end++;
+            p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
+            p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
+                    p_current_packet->p_buffer;
+        }
+    
+        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 */
+    p_netlist->i_pes_end ++;
+    p_netlist->i_pes_end &= p_netlist->i_nb_pes;
+    p_netlist->pp_free_pes[p_netlist->i_pes_end] = p_pes;
+    
+    /* unlock */
+    vlc_mutex_unlock (&p_netlist->lock);
+
+}
+
+/*****************************************************************************
+ * DVDNetlistEnd: frees all allocated structures
+ *****************************************************************************/
+void DVDNetlistEnd( input_thread_t * p_input)
+{
+    netlist_t * p_netlist;
+
+    /* cast */
+    p_netlist = ( netlist_t * ) p_input->p_method_data;
+    
+    /* destroy the mutex lock */
+    vlc_mutex_destroy (&p_netlist->lock);
+    
+    /* free the FIFO, the buffer, and the netlist structure */
+    free (p_netlist->pp_free_data);
+    free (p_netlist->pp_free_pes);
+    free (p_netlist->pi_refcount);
+    free (p_netlist->p_pes);
+    free (p_netlist->p_data);
+    free (p_netlist->p_buffers);
+
+    /* free the netlist */
+    free (p_netlist);
+}
diff --git a/plugins/dvd/dvd_netlist.h b/plugins/dvd/dvd_netlist.h
new file mode 100644 (file)
index 0000000..21cd9c1
--- /dev/null
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * dvd_netlist.h: Specific netlist structures for DVD packets
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
+ * $Id: dvd_netlist.h,v 1.1 2001/03/02 03:32:46 stef Exp $
+ *
+ * Authors: Henri Fallon <henri@videolan.org>
+ *          Stéphane Borel <stef@videolan.org>
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * netlist_t: structure to manage a netlist
+ *****************************************************************************/
+typedef struct netlist_s
+{
+    vlc_mutex_t             lock;
+
+    size_t                  i_buffer_size;
+
+    /* Buffers */
+    byte_t *                p_buffers;                 /* Big malloc'ed area */
+    data_packet_t *         p_data;                        /* malloc'ed area */
+    pes_packet_t *          p_pes;                         /* malloc'ed area */
+
+    /* FIFOs of free packets */
+    data_packet_t **        pp_free_data;
+    pes_packet_t **         pp_free_pes;
+    struct iovec *          p_free_iovec;
+    
+    /* FIFO size */
+    unsigned int            i_nb_iovec;
+    unsigned int            i_nb_pes;
+    unsigned int            i_nb_data;
+
+    /* Index */
+    unsigned int            i_iovec_start, i_iovec_end;
+    unsigned int            i_data_start, i_data_end;
+    unsigned int            i_pes_start, i_pes_end;
+
+    /* Reference counters for iovec */
+    unsigned int *          pi_refcount;
+
+    /* Nb of packets read once */
+    unsigned int            i_read_once;
+
+} netlist_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+int                     DVDNetlistInit( struct input_thread_s *,
+                                        int , int, int, size_t, int );
+
+struct iovec *          DVDGetiovec( void * p_method_data );
+void                    DVDMviovec( void * , int, struct data_packet_s **);
+struct data_packet_s *  DVDNewPtr( void * );
+struct data_packet_s *  DVDNewPacket( void *, size_t );
+struct pes_packet_s *   DVDNewPES( void * );
+void                    DVDDeletePacket( void *, struct data_packet_s * );
+void                    DVDDeletePES( void *, struct pes_packet_s * );
+void                    DVDNetlistEnd( struct input_thread_s * );
index cc74c3aa2f6cd7fcdc75f9e612d7eadc21a17207..8abf09cec07e63bbc10beeaf9e56c3298c7c3466 100644 (file)
@@ -10,7 +10,7 @@
  *  -dvd_udf to find files
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: input_dvd.c,v 1.21 2001/02/26 12:16:28 sam Exp $
+ * $Id: input_dvd.c,v 1.22 2001/03/02 03:32:46 stef Exp $
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
@@ -65,8 +65,8 @@
 #include "input_ext-dec.h"
 
 #include "input.h"
-#include "input_netlist.h"
 
+#include "dvd_netlist.h"
 #include "dvd_ifo.h"
 #include "dvd_css.h"
 #include "input_dvd.h"
@@ -262,10 +262,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
     input.pf_read             = DVDRead;
     input.pf_set_area         = DVDSetArea;
     input.pf_demux            = input_DemuxPS;
-    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       = DVDNewPacket;
+    input.pf_new_pes          = DVDNewPES;
+    input.pf_delete_packet    = DVDDeletePacket;
+    input.pf_delete_pes       = DVDDeletePES;
     input.pf_rewind           = DVDRewind;
     input.pf_seek             = DVDSeek;
 #undef input
@@ -487,7 +487,8 @@ static int DVDSetArea( input_thread_t * p_input,
         {
 
 #if 0
-    fprintf( stderr, "Audio %d: %x %x %x %x %x %x\n", i,
+    fprintf( stderr, "Audio %d: %x %x %x %x %x %x %x\n", i,
+            p_method->ifo.vts.mat.p_audio_atrt[i].i_num_channels,
             p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode,
             p_method->ifo.vts.mat.p_audio_atrt[i].i_multichannel_extension,
             p_method->ifo.vts.mat.p_audio_atrt[i].i_type,
@@ -674,15 +675,17 @@ static void DVDInit( input_thread_t * p_input )
     p_input->p_method_data = NULL;
 
     p_method->i_fd = p_input->i_handle;
-    /* FIXME: read several packets once */
-    p_method->i_read_once = 1; 
+
+    p_method->i_block_once = 32;
+    p_input->i_read_once = 128;
+
     p_method->b_encrypted = DVDCheckCSS( p_input );
 
     lseek( p_input->i_handle, 0, SEEK_SET );
 
     /* Reading structures initialisation */
-    input_NetlistInit( p_input, 4096, 4096, DVD_LB_SIZE,
-                       p_method->i_read_once ); 
+    DVDNetlistInit( p_input, 4096, 16384, 4096, DVD_LB_SIZE,
+                    p_method->i_block_once ); 
     intf_WarnMsg( 2, "DVD: Netlist initialized" );
 
     /* Ifo initialisation */
@@ -781,7 +784,7 @@ static void DVDEnd( input_thread_t * p_input )
 //    IfoEnd( (ifo_t*)(&p_input->p_plugin_data->ifo ) );
     free( p_input->stream.p_demux_data );
     free( p_input->p_plugin_data );
-    input_NetlistEnd( p_input );
+    DVDNetlistEnd( p_input );
 }
 
 /*****************************************************************************
@@ -791,59 +794,57 @@ static void DVDEnd( input_thread_t * p_input )
  * EOF.
  *****************************************************************************/
 static int DVDRead( input_thread_t * p_input,
-                   data_packet_t ** pp_packets )
+                    data_packet_t ** pp_packets )
 {
     thread_dvd_data_t *     p_method;
     netlist_t *             p_netlist;
     struct iovec *          p_vec;
-    struct data_packet_s *  p_data;
+    struct data_packet_s *  pp_data[p_input->i_read_once];
     u8 *                    pi_cur;
     int                     i_packet_size;
+    int                     i_iovec;
     int                     i_packet;
     int                     i_pos;
-    int                     i;
-    boolean_t               b_first_packet;
 
     p_method = ( thread_dvd_data_t * ) p_input->p_plugin_data;
     p_netlist = ( netlist_t * ) p_input->p_method_data;
 
     /* Get an iovec pointer */
-    if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL )
+    if( ( p_vec = DVDGetiovec( p_netlist ) ) == NULL )
     {
         intf_ErrMsg( "DVD: read error" );
         return -1;
     }
 
     /* Reads from DVD */
-    readv( p_input->i_handle, p_vec, p_method->i_read_once );
+    readv( p_input->i_handle, p_vec, p_method->i_block_once );
 
-    if( p_method->b_encrypted )
+    /* Update netlist indexes */
+    DVDMviovec( p_netlist, p_method->i_block_once, pp_data );
+    i_packet = 0;
+
+    /* Read headers to compute payload length */
+    for( i_iovec = 0 ; i_iovec < p_method->i_block_once ; i_iovec++ )
     {
-        for( i=0 ; i<p_method->i_read_once ; i++ )
+        if( p_method->b_encrypted )
         {
             CSSDescrambleSector( p_method->css.pi_title_key, 
-                                 p_vec[i].iov_base );
-            ((u8*)(p_vec[i].iov_base))[0x14] &= 0x8F;
+                                 p_vec[i_iovec].iov_base );
+            ((u8*)(p_vec[i_iovec].iov_base))[0x14] &= 0x8F;
         }
-    }
-
-    /* Update netlist indexes */
-    input_NetlistMviovec( p_netlist, p_method->i_read_once, &p_data );
 
-    i_packet = 0;
-    /* Read headers to compute payload length */
-    for( i = 0 ; i < p_method->i_read_once ; i++ )
-    {
         i_pos = 0;
-        b_first_packet = 1;
+
         while( i_pos < p_netlist->i_buffer_size )
         {
-            pi_cur = (u8*)(p_vec[i].iov_base + i_pos);
+            pi_cur = (u8*)(p_vec[i_iovec].iov_base + i_pos);
+
             /*default header */
             if( U32_AT( pi_cur ) != 0x1BA )
             {
                 /* That's the case for all packets, except pack header. */
                 i_packet_size = U16_AT( pi_cur + 4 );
+                pp_packets[i_packet] = DVDNewPtr( p_netlist );
             }
             else
             {
@@ -863,31 +864,33 @@ static int DVDRead( input_thread_t * p_input,
                     intf_ErrMsg( "Unable to determine stream type" );
                     return( -1 );
                 }
+
+                pp_packets[i_packet] = pp_data[i_iovec];
+
             }
-            if( b_first_packet )
-            {
-                p_data->b_discard_payload = 0;
-                b_first_packet = 0;
-            }
-            else
-            { 
-                p_data = input_NetlistNewPacket( p_netlist ,
-                                                 i_packet_size + 6 );
-                memcpy( p_data->p_buffer,
-                        p_vec[i].iov_base + i_pos , i_packet_size + 6 );
-            }
 
-            p_data->p_payload_end = p_data->p_payload_start + i_packet_size + 6;
-            pp_packets[i_packet] = p_data;
+            (*pp_data[i_iovec]->pi_refcount)++;
+
+            pp_packets[i_packet]->pi_refcount = pp_data[i_iovec]->pi_refcount;
+
+            pp_packets[i_packet]->p_buffer = pp_data[i_iovec]->p_buffer;
+
+            pp_packets[i_packet]->p_payload_start =
+                    pp_packets[i_packet]->p_buffer + i_pos;
+
+            pp_packets[i_packet]->p_payload_end =
+                    pp_packets[i_packet]->p_payload_start + i_packet_size + 6;
+
             i_packet++;
             i_pos += i_packet_size + 6;
         }
     }
+
     pp_packets[i_packet] = NULL;
 
     vlc_mutex_lock( &p_input->stream.stream_lock );
     p_input->stream.p_selected_area->i_tell +=
-                                        p_method->i_read_once *DVD_LB_SIZE;
+                                        p_method->i_block_once *DVD_LB_SIZE;
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     return( 0 );
index 8c2cee89eba900b6247f7d3692843c25a761c223..b50f2a74766747db25073d2d0908596f82ab2d4d 100644 (file)
@@ -33,7 +33,9 @@ typedef struct thread_dvd_data_s
 {
     int                     i_fd;               // File descriptor of device
     boolean_t               b_encrypted;        // CSS encryption
-    int                     i_read_once;        // NB of bytes read by DVDRead
+
+    int                     i_block_once;       // Nb of block read once by 
+                                                // readv
 
     int                     i_chapter_nb;
     off_t                   i_start;
index 8cb868a944325a14b2c5583a6883f646dd8b2dc2..e9743a58fb3a6217de4972f8e3a61f9a0cfd2a30 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input.c,v 1.87 2001/02/20 09:10:36 sam Exp $
+ * $Id: input.c,v 1.88 2001/03/02 03:32:46 stef Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -89,6 +89,9 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
         return( NULL );
     }
 
+    /* Packets read once */
+    p_input->i_read_once = INPUT_READ_ONCE;
+
     /* Initialize thread properties */
     p_input->b_die              = 0;
     p_input->b_error            = 0;
@@ -193,7 +196,6 @@ 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];
     int                     i_error, i;
 
     if( InitThread( p_input ) )
@@ -209,6 +211,7 @@ static void RunThread( input_thread_t *p_input )
 
     while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
     {
+        data_packet_t *         pp_packets[p_input->i_read_once];
 
 #ifdef STATS
         p_input->c_loops++;
@@ -241,7 +244,7 @@ static void RunThread( input_thread_t *p_input )
         i_error = p_input->pf_read( p_input, pp_packets );
 
         /* Demultiplex read packets. */
-        for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
+        for( i = 0; i < p_input->i_read_once && pp_packets[i] != NULL; i++ )
         {
             p_input->pf_demux( p_input, pp_packets[i] );
         }
index de041b53ac491d817b9023d555d702b52b04d155..064576ece1b3533f645abfb39d3933f310c93ba2 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.38 2001/02/21 04:38:59 henri Exp $
+ * $Id: mpeg_system.c,v 1.39 2001/03/02 03:32:46 stef Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -500,11 +500,11 @@ static u16 GetID( data_packet_t * p_data )
 {
     u16         i_id;
 
-    i_id = p_data->p_buffer[3];                                 /* stream_id */
+    i_id = p_data->p_payload_start[3];                                 /* stream_id */
     if( i_id == 0xBD )
     {
         /* stream_private_id */
-        i_id |= p_data->p_buffer[ 9 + p_data->p_buffer[8] ] << 8;
+        i_id |= p_data->p_payload_start[ 9 + p_data->p_payload_start[8] ] << 8;
     }
     return( i_id );
 }
@@ -528,7 +528,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
     }
 
     if( p_demux->b_has_PSM
-        && p_demux->i_PSM_version == (p_data->p_buffer[6] & 0x1F) )
+        && p_demux->i_PSM_version == (p_data->p_payload_start[6] & 0x1F) )
     {
         /* Already got that one. */
         return;
@@ -536,7 +536,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
 
     intf_DbgMsg( "Building PSM" );
     p_demux->b_has_PSM = 1;
-    p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F;
+    p_demux->i_PSM_version = p_data->p_payload_start[6] & 0x1F;
 
     /* Go to elementary_stream_map_length, jumping over
      * program_stream_info. */
@@ -647,7 +647,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
     u32                 i_code;
     es_descriptor_t *   p_es = NULL;
 
-    i_code = U32_AT( p_data->p_buffer );
+    i_code = U32_AT( p_data->p_payload_start );
     if( i_code > 0x1BC ) /* ES start code */
     {
         u16                 i_id;
@@ -685,7 +685,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
                                     i_id, 0 );
                 if( p_es != NULL )
                 {
-                    p_es->i_stream_id = p_data->p_buffer[3];
+                    p_es->i_stream_id = p_data->p_payload_start[3];
 
                     /* Set stream type and auto-spawn. */
                     if( (i_id & 0xF0) == 0xE0 )
@@ -777,7 +777,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
     boolean_t           b_trash = 0;
     es_descriptor_t *   p_es = NULL;
 
-    i_code = U32_AT( p_data->p_buffer );
+    i_code = U32_AT( p_data->p_payload_start );
     if( i_code <= 0x1BC )
     {
         switch( i_code )
@@ -788,30 +788,30 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
                 mtime_t         scr_time;
                 u32             i_mux_rate;
 
-                if( (p_data->p_buffer[4] & 0xC0) == 0x40 )
+                if( (p_data->p_payload_start[4] & 0xC0) == 0x40 )
                 {
                     /* MPEG-2 */
                     scr_time =
-                         ((mtime_t)(p_data->p_buffer[4] & 0x38) << 27) |
-                         ((mtime_t)(U32_AT(p_data->p_buffer + 4) & 0x03FFF800)
+                         ((mtime_t)(p_data->p_payload_start[4] & 0x38) << 27) |
+                         ((mtime_t)(U32_AT(p_data->p_payload_start + 4) & 0x03FFF800)
                                         << 4) |
-                         ((mtime_t)(U32_AT(p_data->p_buffer + 6) & 0x03FFF800)
+                         ((mtime_t)(U32_AT(p_data->p_payload_start + 6) & 0x03FFF800)
                                         >> 11);
 
                     /* mux_rate */
-                    i_mux_rate = (U32_AT(p_data->p_buffer + 10) & 0xFFFFFC00);
+                    i_mux_rate = (U32_AT(p_data->p_payload_start + 10) & 0xFFFFFC00);
                 }
                 else
                 {
                     /* MPEG-1 SCR is like PTS. */
                     scr_time =
-                         ((mtime_t)(p_data->p_buffer[4] & 0x0E) << 29) |
-                         (((mtime_t)U16_AT(p_data->p_buffer + 5) << 14)
+                         ((mtime_t)(p_data->p_payload_start[4] & 0x0E) << 29) |
+                         (((mtime_t)U16_AT(p_data->p_payload_start + 5) << 14)
                            - (1 << 14)) |
-                         ((mtime_t)U16_AT(p_data->p_buffer + 7) >> 1);
+                         ((mtime_t)U16_AT(p_data->p_payload_start + 7) >> 1);
 
                     /* mux_rate */
-                    i_mux_rate = (U32_AT(p_data->p_buffer + 8) & 0x8FFFFE);
+                    i_mux_rate = (U32_AT(p_data->p_payload_start + 8) & 0x8FFFFE);
                 }
                 /* Call the pace control. */
                 input_ClockManageRef( p_input, p_input->stream.pp_programs[0],