]> git.sesse.net Git - vlc/commitdiff
The input-II. (more info by mail in about an hour)
authorChristophe Massiot <massiot@videolan.org>
Tue, 5 Dec 2000 19:36:58 +0000 (19:36 +0000)
committerChristophe Massiot <massiot@videolan.org>
Tue, 5 Dec 2000 19:36:58 +0000 (19:36 +0000)
64 files changed:
Makefile.in
include/config.h.in
include/decoder_fifo.h [deleted file]
include/input.h [deleted file]
include/input_ext-dec.h [new file with mode: 0644]
include/input_ext-intf.h [new file with mode: 0644]
include/input_netlist.h [deleted file]
include/input_ps.h [deleted file]
include/stream_control.h [new file with mode: 0644]
include/video_parser.h
plugins/dummy/intf_dummy.c
plugins/fb/intf_fb.c
plugins/ggi/intf_ggi.c
plugins/glide/intf_glide.c
plugins/gnome/intf_gnome.c
plugins/mga/intf_mga.c
plugins/sdl/intf_sdl.c
plugins/x11/intf_x11.c
src/ac3_decoder/ac3_decoder.h [moved from include/ac3_decoder.h with 100% similarity]
src/ac3_decoder/ac3_decoder_thread.c
src/ac3_decoder/ac3_decoder_thread.h [moved from include/ac3_decoder_thread.h with 86% similarity]
src/audio_decoder/audio_decoder.h [moved from include/audio_decoder.h with 100% similarity]
src/audio_decoder/audio_decoder_thread.c
src/audio_decoder/audio_decoder_thread.h [moved from include/audio_decoder_thread.h with 87% similarity]
src/input/input.c
src/input/input.h [new file with mode: 0644]
src/input/input_ctrl.c [deleted file]
src/input/input_ctrl.h [deleted file]
src/input/input_ext-dec.c [new file with mode: 0644]
src/input/input_file.c [deleted file]
src/input/input_file.h [deleted file]
src/input/input_netlist.c [deleted file]
src/input/input_network.c [deleted file]
src/input/input_network.h [deleted file]
src/input/input_pcr.c [deleted file]
src/input/input_pcr.h [deleted file]
src/input/input_ps.c [new file with mode: 0644]
src/input/input_ps.h [new file with mode: 0644]
src/input/input_psi.c [deleted file]
src/input/input_psi.h [deleted file]
src/input/input_ts.c [moved from include/input_vlan.h with 52% similarity]
src/input/input_ts.h [new file with mode: 0644]
src/input/input_vlan.c [deleted file]
src/input/mpeg_system.c [new file with mode: 0644]
src/input/mpeg_system.h [new file with mode: 0644]
src/interface/interface.c
src/interface/intf_ctrl.c
src/interface/main.c
src/lpcm_decoder/lpcm_decoder.h [moved from include/lpcm_decoder.h with 100% similarity]
src/lpcm_decoder/lpcm_decoder_thread.c
src/lpcm_decoder/lpcm_decoder_thread.h [moved from include/lpcm_decoder_thread.h with 86% similarity]
src/misc/decoder_fifo.c [deleted file]
src/spu_decoder/spu_decoder.c
src/spu_decoder/spu_decoder.h [moved from include/spu_decoder.h with 92% similarity]
src/video_decoder/vdec_idct.c
src/video_decoder/vdec_motion.c
src/video_decoder/vdec_motion_inner.c
src/video_decoder/vdec_motion_inner_mmx.c
src/video_decoder/video_decoder.c
src/video_parser/video_fifo.c
src/video_parser/video_parser.c
src/video_parser/vpar_blocks.c
src/video_parser/vpar_headers.c
src/video_parser/vpar_synchro.c

index f1b1b08af327def22b05e1a8f2a399786846ff84..dfa0d8c25d32cabe7b957733d334ec5adbad056f 100644 (file)
@@ -100,7 +100,7 @@ ifeq ($(OPTIMS),1)
 CFLAGS += -O6
 CFLAGS += -ffast-math -funroll-loops -fargument-noalias-global
 CFLAGS += -funroll-all-loops -fstrict-aliasing
-CFLAGS += -fomit-frame-pointer
+#CFLAGS += -fomit-frame-pointer
 
 # Optimizations for x86 familiy
 ifneq (,$(findstring 86,$(ARCH)))
@@ -176,13 +176,9 @@ interface_obj =    interface/main.o \
                                interface/intf_ctrl.o \
                                interface/intf_console.o
 
-input_obj =            input/input_vlan.o \
-                               input/input_file.o \
-                               input/input_netlist.o \
-                               input/input_network.o \
-                               input/input_ctrl.o \
-                               input/input_pcr.o \
-                               input/input_psi.o \
+input_obj =            input/input_ps.o \
+                               input/mpeg_system.o \
+                               input/input_ext-dec.o \
                                input/input.o
 
 audio_output_obj =     audio_output/audio_output.o
@@ -236,8 +232,7 @@ misc_obj =          misc/mtime.o \
                                misc/rsc_files.o \
                                misc/netutils.o \
                                misc/playlist.o \
-                               misc/plugins.o \
-                               misc/decoder_fifo.o
+                               misc/plugins.o
 
 
 C_OBJ = $(interface_obj) \
index c7d65faf7dbd7045cf72c535801f23353e6278c7..4d9dd6399ba71a60c20db35b1611c2b4fd98f9a9 100644 (file)
 
 /* Duration between the time we receive the TS packet, and the time we will
  * mark it to be presented */
-#define INPUT_PTS_DELAY                 (.5*CLOCK_FREQ)
+#define DEFAULT_PTS_DELAY               (.5*CLOCK_FREQ)
 
 #define INPUT_DVD_AUDIO_VAR             "vlc_dvd_audio"
 #define INPUT_DVD_CHANNEL_VAR           "vlc_dvd_channel"
diff --git a/include/decoder_fifo.h b/include/decoder_fifo.h
deleted file mode 100644 (file)
index a2a13f4..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-/*****************************************************************************
- * decoder_fifo.h: interface for decoders PES fifo
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Michel Kaempf <maxx@via.ecp.fr>
- *          Christophe Massiot <massiot@via.ecp.fr>
- *          Michel Lespinasse <walken@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Required headers:
- * - "config.h"
- * - "common.h"
- * - "threads.h"
- * - "input.h"
- *****************************************************************************/
-
-#define WORD_TYPE           u32
-#define WORD_BYTE_LENGTH    4
-#define WORD_LENGTH         32
-
-/*****************************************************************************
- * Macros
- *****************************************************************************/
-
-/* FIXME: move to inline functions ??*/
-#define DECODER_FIFO_ISEMPTY( fifo )  ( (fifo).i_start == (fifo).i_end )
-#define DECODER_FIFO_ISFULL( fifo )   ( ( ((fifo).i_end + 1 - (fifo).i_start)\
-                                          & FIFO_SIZE ) == 0 )
-#define DECODER_FIFO_START( fifo )    ( (fifo).buffer[ (fifo).i_start ] )
-#define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
-                                                         & FIFO_SIZE )
-#define DECODER_FIFO_END( fifo )      ( (fifo).buffer[ (fifo).i_end ] )
-#define DECODER_FIFO_INCEND( fifo )   ( (fifo).i_end = ((fifo).i_end + 1) \
-                                                       & FIFO_SIZE )
-
-/*****************************************************************************
- * decoder_fifo_t
- *****************************************************************************
- * This rotative FIFO contains PES packets that are to be decoded...
- *****************************************************************************/
-typedef struct
-{
-    vlc_mutex_t         data_lock;                         /* fifo data lock */
-    vlc_cond_t          data_wait;         /* fifo data conditional variable */
-
-    /* buffer is an array of PES packets pointers */
-    pes_packet_t *      buffer[FIFO_SIZE + 1];
-    int                 i_start;
-    int                 i_end;
-
-} decoder_fifo_t;
-
-/*****************************************************************************
- * bit_fifo_t : bit fifo descriptor
- *****************************************************************************
- * This type describes a bit fifo used to store bits while working with the
- * input stream at the bit level.
- *****************************************************************************/
-typedef struct bit_fifo_s
-{
-    /* This unsigned integer allows us to work at the bit level. This buffer
-     * can contain 32 bits, and the used space can be found on the MSb's side
-     * and the available space on the LSb's side. */
-    WORD_TYPE           buffer;
-
-    /* Number of bits available in the bit buffer */
-    int                 i_available;
-
-} bit_fifo_t;
-
-/*****************************************************************************
- * bit_stream_t : bit stream descriptor
- *****************************************************************************
- * This type, based on a PES stream, includes all the structures needed to
- * handle the input stream like a bit stream.
- *****************************************************************************/
-typedef struct bit_stream_s
-{
-    /*
-     * Input structures
-     */
-    /* The input thread feeds the stream with fresh PES packets */
-    input_thread_t *    p_input;
-    /* The decoder fifo contains the data of the PES stream */
-    decoder_fifo_t *    p_decoder_fifo;
-
-    /*
-     * Byte structures
-     */
-    /* Current TS packet (in the current PES packet of the PES stream) */
-    ts_packet_t *       p_ts;
-   /* Pointer to the next byte that is to be read (in the current TS packet) */
-    byte_t *            p_byte;
-    /* Pointer to the last byte that is to be read (in the current TS packet */
-    byte_t *            p_end;
-
-    /*
-     * Bit structures
-     */
-    bit_fifo_t          fifo;
-
-} bit_stream_t;
-
-
-void decoder_fifo_next( bit_stream_t * p_bit_stream );
-/*****************************************************************************
- * GetByte : reads the next byte in the input stream
- *****************************************************************************/
-static __inline__ byte_t GetByte( bit_stream_t * p_bit_stream )
-{
-    /* Are there some bytes left in the current TS packet ? */
-    /* could change this test to have a if (! (bytes--)) instead */
-    if ( p_bit_stream->p_byte >= p_bit_stream->p_end )
-    {
-        /* no, switch to next TS packet */
-        decoder_fifo_next( p_bit_stream );
-    }
-
-    return( *(p_bit_stream->p_byte++));
-}
-
-/*****************************************************************************
- * NeedBits : reads i_bits new bits in the bit stream and stores them in the
- *            bit buffer
- *****************************************************************************
- * - i_bits must be less or equal 32 !
- * - There is something important to notice with that function : if the number
- * of bits available in the bit buffer when calling NeedBits() is greater than
- * 24 (i_available > 24) but less than the number of needed bits
- * (i_available < i_bits), the byte returned by GetByte() will be shifted with
- * a negative value and the number of bits available in the bit buffer will be
- * set to more than 32 !
- *****************************************************************************/
-static __inline__ void NeedBits( bit_stream_t * p_bit_stream, int i_bits )
-{
-    while ( p_bit_stream->fifo.i_available < i_bits )
-    {
-        p_bit_stream->fifo.buffer |= ((u32)GetByte( p_bit_stream )) << (24 - p_bit_stream->fifo.i_available);
-        p_bit_stream->fifo.i_available += 8;
-    }
-}
-
-/*****************************************************************************
- * DumpBits : removes i_bits bits from the bit buffer
- *****************************************************************************
- * - i_bits <= i_available
- * - i_bits < 32 (because (u32 << 32) <=> (u32 = u32))
- *****************************************************************************/
-static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int i_bits )
-{
-    p_bit_stream->fifo.buffer <<= i_bits;
-    p_bit_stream->fifo.i_available -= i_bits;
-}
-
-/*****************************************************************************
- * DumpBits32 : removes 32 bits from the bit buffer
- *****************************************************************************
- * This function actually believes that you have already put 32 bits in the
- * bit buffer, so you can't use it anytime.
- *****************************************************************************/
-static __inline__ void DumpBits32( bit_stream_t * p_bit_stream )
-{
-    p_bit_stream->fifo.buffer = 0;
-    p_bit_stream->fifo.i_available = 0;
-}
-
-/*
- * For the following functions, please read VERY CAREFULLY the warning in
- * NeedBits(). If i_bits > 24, the stream parser must be already aligned
- * on an 8-bit boundary, or you will get curious results (that is, you
- * need to call RealignBits() before).
- */
-
-void PeekNextPacket( bit_stream_t * p_bit_stream );
-
-//(stolen from the kernel)
-// XXX: The macro swab32 for little endian machine does
-//      not seem to work correctly
-
-#if defined(SYS_BEOS)
-#       define swab32(x) B_BENDIAN_TO_HOST_INT32(x)
-#else
-#    if __BYTE_ORDER == __BIG_ENDIAN
-#        define swab32(x) (x)
-#    else
-#        if defined (__i386__)
-#           define swab32(x) __i386_swab32(x)
-static inline const u32 __i386_swab32(u32 x)
-{
-    __asm__("bswap %0" : "=r" (x) : "0" (x));
-    return x;
-}
-#        else
-#           define swab32(x)\
-            ( ( (u32)(((u8*)&x)[0]) << 24 ) | ( (u32)(((u8*)&x)[1]) << 16 ) |  \
-              ( (u32)(((u8*)&x)[2]) << 8 )  | ( (u32)(((u8*)&x)[3])) )
-#        endif
-#    endif
-#endif
-
-
-static __inline__ WORD_TYPE GetWord( bit_stream_t * p_bit_stream )
-{
-    if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
-    {
-        return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
-    }
-    else
-    {
-        PeekNextPacket( p_bit_stream );
-        return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
-    }
-}
-
-/*****************************************************************************
- * RemoveBits : removes i_bits bits from the bit buffer
- *****************************************************************************/
-static __inline__ void RemoveBits( bit_stream_t * p_bit_stream, int i_bits )
-{
-    p_bit_stream->fifo.i_available -= i_bits;
-
-    if( p_bit_stream->fifo.i_available >= 0 )
-    {
-        p_bit_stream->fifo.buffer <<= i_bits;
-        return;
-    }
-    p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
-                            << ( -p_bit_stream->fifo.i_available );
-    p_bit_stream->fifo.i_available += WORD_LENGTH;
-}
-
-/*****************************************************************************
- * RemoveBits32 : removes 32 bits from the bit buffer (and as a side effect,
- * refill it)
- *****************************************************************************/
-static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
-{
-    p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
-                        << (32 - p_bit_stream->fifo.i_available);
-}
-
-/*****************************************************************************
- * ShowBits : return i_bits bits from the bit stream
- *****************************************************************************/
-static __inline__ WORD_TYPE ShowWord( bit_stream_t * p_bit_stream )
-{
-    if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
-    {
-        return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
-    }
-
-    PeekNextPacket( p_bit_stream );
-    return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
-}
-
-static __inline__ u32 ShowBits( bit_stream_t * p_bit_stream, int i_bits )
-{
-    if( p_bit_stream->fifo.i_available >= i_bits )
-    {
-        return( p_bit_stream->fifo.buffer >> (32 - i_bits) );
-    }
-
-    return( (p_bit_stream->fifo.buffer |
-            (ShowWord( p_bit_stream ) >> p_bit_stream->fifo.i_available))
-                    >> (32 - i_bits) );
-}
-
-/*****************************************************************************
- * GetBits : returns i_bits bits from the bit stream and removes them
- *****************************************************************************/
-static __inline__ u32 GetBits( bit_stream_t * p_bit_stream, int i_bits )
-{
-    u32             i_result;
-
-    p_bit_stream->fifo.i_available -= i_bits;
-    if( p_bit_stream->fifo.i_available >= 0 )
-    {
-        i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
-        p_bit_stream->fifo.buffer <<= i_bits;
-        return( i_result );
-    }
-
-    i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
-    p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
-    i_result |= p_bit_stream->fifo.buffer
-                             >> (32 + p_bit_stream->fifo.i_available);
-    p_bit_stream->fifo.buffer <<= ( -p_bit_stream->fifo.i_available );
-    p_bit_stream->fifo.i_available += WORD_LENGTH;
-
-    return( i_result );
-}
-
-/*****************************************************************************
- * GetBits32 : returns 32 bits from the bit stream and removes them
- *****************************************************************************/
-static __inline__ u32 GetBits32( bit_stream_t * p_bit_stream )
-{
-    u32             i_result;
-
-    i_result = p_bit_stream->fifo.buffer;
-    p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
-    i_result |= p_bit_stream->fifo.buffer
-                             >> (p_bit_stream->fifo.i_available);
-    p_bit_stream->fifo.buffer <<= (32 - p_bit_stream->fifo.i_available);
-    
-    return( i_result );
-}
-
-/*****************************************************************************
- * RealignBits : realigns the bit buffer on an 8-bit boundary
- *****************************************************************************/
-static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
-{
-    p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
-    p_bit_stream->fifo.i_available &= ~0x7;
-}
-
diff --git a/include/input.h b/include/input.h
deleted file mode 100644 (file)
index 8102179..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-/*****************************************************************************
- * input.h: input thread interface
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *          Vincent Seguin <seguin@via.ecp.fr>
- *          Benoît Steiner <benny@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Constants related to input
- *****************************************************************************/
-#define TS_PACKET_SIZE      188                       /* size of a TS packet */
-#define PES_HEADER_SIZE     14     /* size of the first part of a PES header */
-#define PSI_SECTION_SIZE    4096            /* Maximum size of a PSI section */
-
-/*****************************************************************************
- * ts_packet_t
- *****************************************************************************
- * Describe a TS packet.
- *****************************************************************************/
-typedef struct ts_packet_s
-{
-    /* Nothing before this line, the code relies on that */
-    byte_t                  buffer[TS_PACKET_SIZE];    /* raw TS data packet */
-
-    /* Decoders information */
-    unsigned int            i_payload_start;
-                                  /* start of the PES payload in this packet */
-    unsigned int            i_payload_end;                    /* guess ? :-) */
-
-    /* Used to chain the TS packets that carry data for a same PES or PSI */
-    struct ts_packet_s      *  p_prev_ts;
-    struct ts_packet_s      *  p_next_ts;
-} ts_packet_t;
-
-/*****************************************************************************
- * pes_packet_t
- *****************************************************************************
- * Describes an PES packet, with its properties, and pointers to the TS packets
- * containing it.
- *****************************************************************************/
-typedef struct pes_packet_s
-{
-    /* PES properties */
-    boolean_t               b_data_loss;  /* The previous (at least) PES packet
-           * has been lost. The decoders will have to find a way to recover. */
-    boolean_t               b_data_alignment;  /* used to find the beginning of
-                                                * a video or audio unit      */
-    boolean_t               b_has_pts;       /* is the following field set ? */
-    mtime_t                 i_pts; /* the PTS for this packet (if set above) */
-    boolean_t               b_random_access;
-            /* if TRUE, in the payload of this packet, there is the first byte
-             * of a video sequence header, or the first byte of an audio frame.
-             */
-    u8                      i_stream_id;              /* payload type and id */
-    int                     i_pes_size;    /* size of the current PES packet */
-    int                     i_pes_real_size;      /* real size of the current
-                                                   * PES packet, ie. the one
-                                                   * announced in the header */
-    int                     i_ts_packets;/* number of TS packets in this PES */
-
-    /* Demultiplexer environment */
-    boolean_t               b_discard_payload;  /* is the packet messed up ? */
-    byte_t *                p_pes_header;       /* pointer to the PES header */
-    byte_t *                p_pes_header_save;           /* temporary buffer */
-
-    /* Pointers to TS packets (TS packets are then linked by the p_prev_ts and
-       p_next_ts fields of the ts_packet_t struct) */
-    ts_packet_t *           p_first_ts;   /* The first TS packet containing this
-                                           * PES (used by decoders). */
-    ts_packet_t *           p_last_ts; /* The last TS packet gathered at present
-                                        * (used by the demultiplexer). */
-} pes_packet_t;
-
-/*****************************************************************************
- * psi_section_t
- *****************************************************************************
- * Describes a PSI section. Beware, it doesn't contain pointers to the TS
- * packets that contain it as for a PES, but the data themselves
- *****************************************************************************/
-typedef struct psi_section_s
-{
-    byte_t        buffer[PSI_SECTION_SIZE];
-
-    boolean_t     b_running_section;   /* Is there a section being decoded ? */
-
-    u16 i_length;
-    u16 i_current_position;
-} psi_section_t;
-
-
-/*****************************************************************************
- * es_descriptor_t: elementary stream descriptor
- *****************************************************************************
- * Describes an elementary stream, and includes fields required to handle and
- * demultiplex this elementary stream.
- *****************************************************************************/
-typedef struct es_descriptor_t
-{
-    u16                     i_id;           /* stream ID, PID for TS streams */
-    u8                      i_type;                           /* stream type */
-
-    boolean_t               b_pcr;        /* does the stream include a PCR ? */
-    /* XXX?? b_pcr will be replaced by something else: since a PCR can't be shared
-     * between several ES, we will probably store the PCR fields directly here,
-     * and one of those fields will probably (again) be used as a test of the
-     * PCR presence */
-    boolean_t               b_psi;  /* does the stream have to be handled by the
-                                                                PSI decoder ? */
-    /* Markers */
-    int                     i_continuity_counter;
-    boolean_t               b_discontinuity;
-    boolean_t               b_random;
-
-    /* PES packets */
-    pes_packet_t *          p_pes_packet;
-                                      /* current PES packet we are gathering */
-
-    /* PSI packets */
-    psi_section_t *         p_psi_section;          /* idem for a PSI stream */
-
-    /* Decoder informations */
-    void *                  p_dec;     /* p_dec is void *, since we don't know a
-                                        * priori whether it is adec_thread_t or
-                                        * vdec_thread_t. We will use explicit
-                                        * casts. */
-
-    /* XXX?? video stream descriptor ? */
-    /* XXX?? audio stream descriptor ? */
-    /* XXX?? hierarchy descriptor ? */
-    /* XXX?? target background grid descriptor ? */
-    /* XXX?? video window descriptor ? */
-    /* XXX?? ISO 639 language descriptor ? */
-
-#ifdef STATS
-    /* Stats */
-    count_t                 c_bytes;                     /* total bytes read */
-    count_t                 c_payload_bytes;/* total of payload useful bytes */
-    count_t                 c_packets;                 /* total packets read */
-    count_t                 c_invalid_packets;       /* invalid packets read */
-    /* XXX?? ... other stats */
-#endif
-} es_descriptor_t;
-
-/* Special PID values - note that the PID is only on 13 bits, and that values
- * greater than 0x1fff have no meaning in a stream */
-#define PROGRAM_ASSOCIATION_TABLE_PID   0x0000
-#define CONDITIONNAL_ACCESS_TABLE_PID   0x0001                   /* not used */
-#define EMPTY_PID                       0xffff    /* empty record in a table */
-
-/* ES streams types - see ISO/IEC 13818-1 table 2-29 numbers */
-#define MPEG1_VIDEO_ES          0x01
-#define MPEG2_VIDEO_ES          0x02
-#define MPEG1_AUDIO_ES          0x03
-#define MPEG2_AUDIO_ES          0x04
-#define AC3_AUDIO_ES            0x81
-#define DVD_SPU_ES             0x82           /* 0x82 might violate the norm */
-#define LPCM_AUDIO_ES           0x83
-/*****************************************************************************
- * program_descriptor_t
- *****************************************************************************
- * Describes a program and list associated elementary streams. It is build by
- * the PSI decoder upon the informations carried in program map sections
- *****************************************************************************/
-typedef struct
-{
-    /* Program characteristics */
-    u16                     i_number;                      /* program number */
-    u8                      i_version;                     /* version number */
-    boolean_t               b_is_ok;       /* Is the description up to date ?*/
-    u16                     i_pcr_pid;                             /* PCR ES */
-
-    int i_es_number;
-    es_descriptor_t **      ap_es;                /* array of pointers to ES */
-
-#ifdef DVB_EXTENSIONS
-    /* Service Descriptor (program name) */
-    u8                      i_srv_type;
-    char*                   psz_srv_name;
-#endif
-
-    /* XXX?? target background grid descriptor ? */
-    /* XXX?? video window descriptor ? */
-    /* XXX?? ISO 639 language descriptor ? */
-
-#ifdef STATS
-    /* Stats */
-    /* XXX?? ...stats */
-#endif
-} pgrm_descriptor_t;
-
-/*****************************************************************************
- * pcr_descriptor_t
- *****************************************************************************
- * Contains informations used to synchronise the decoder with the server
- *****************************************************************************/
-
-typedef struct pcr_descriptor_struct
-{
-    /* system_date = PTS_date + delta_pcr + delta_absolute */
-    mtime_t                 delta_pcr;
-    mtime_t                 delta_absolute;
-
-    mtime_t                 last_pcr;
-
-    u32                     i_synchro_state;
-    count_t                 c_average_count;
-                           /* counter used to compute dynamic average values */
-} pcr_descriptor_t;
-
-/*****************************************************************************
- * stream_descriptor_t
- *****************************************************************************
- * Describes a transport stream and list its associated programs. Build upon
- * the informations carried in program association sections
- *****************************************************************************/
-typedef struct
-{
-    u16                     i_stream_id;                        /* stream id */
-
-    /* Program Association Table status */
-    u8                      i_PAT_version;                 /* version number */
-    boolean_t               b_is_PAT_complete;       /* Is the PAT complete ?*/
-    u8                      i_known_PAT_sections;
-                                     /* Number of section we received so far */
-    byte_t                  a_known_PAT_sections[32];
-                                                /* Already received sections */
-
-    /* Program Map Table status */
-    boolean_t               b_is_PMT_complete;       /* Is the PMT complete ?*/
-    u8                      i_known_PMT_sections;
-                                     /* Number of section we received so far */
-    byte_t                  a_known_PMT_sections[32];
-                                                /* Already received sections */
-
-    /* Service Description Table status */
-    u8                      i_SDT_version;                 /* version number */
-    boolean_t               b_is_SDT_complete;       /* Is the SDT complete ?*/
-    u8                      i_known_SDT_sections;
-                                     /* Number of section we received so far */
-    byte_t                  a_known_SDT_sections[32];
-                                                /* Already received sections */
-
-    /* Programs description */
-    int i_pgrm_number;                   /* Number of program number we have */
-    pgrm_descriptor_t **    ap_programs;        /* Array of pointers to pgrm */
-
-#ifdef STATS
-    /* Stats */
-    /* XXX?? ...stats */
-#endif
-} stream_descriptor_t;
-
-/*****************************************************************************
- * input_netlist_t
- *****************************************************************************/
-typedef struct
-{
-    vlc_mutex_t             lock;               /* netlist modification lock */
-    struct iovec            p_ts_free[INPUT_MAX_TS + INPUT_TS_READ_ONCE];
-                                          /* FIFO or LIFO of free TS packets */
-    ts_packet_t *           p_ts_packets;
-                              /* pointer to the first TS packet we allocated */
-
-    pes_packet_t *          p_pes_free[INPUT_MAX_PES + 1];
-                                         /* FIFO or LIFO of free PES packets */
-    pes_packet_t *          p_pes_packets;
-                             /* pointer to the first PES packet we allocated */
-
-    /* To use the efficiency of the scatter/gather IO operations. We implemented
-     * it in 2 ways, as we don't know yet which one is better : as a FIFO (code
-     * simplier) or as a LIFO stack (when we doesn't care of the ordering, this
-     * allow to drastically improve the cache performance) */
-#ifdef INPUT_LIFO_TS_NETLIST
-    int                     i_ts_index;
-#else
-    int                     i_ts_start, i_ts_end;
-#endif
-#ifdef INPUT_LIFO_PES_NETLIST
-    int                     i_pes_index;
-#else
-    int                     i_pes_start, i_pes_end;
-#endif
-} input_netlist_t;
-
-
-
-/*****************************************************************************
- * input_thread_t
- *****************************************************************************
- * This structure includes all the local static variables of an input thread,
- * including the netlist and the ES descriptors
- * Note that p_es must be defined as a static table, otherwise we would have to
- * update all reference to it each time the table would be reallocated
- *****************************************************************************/
-
-/* Function pointers used in structure */
-typedef int  (input_open_t)     ( p_input_thread_t p_input );
-typedef int  (input_read_t)     ( p_input_thread_t p_input, const struct iovec *p_vector,
-                                   size_t i_count );
-typedef void (input_close_t)    ( p_input_thread_t p_input );
-
-/* Structure */
-typedef struct input_thread_s
-{
-    /* Thread properties and locks */
-    boolean_t                   b_die;                         /* 'die' flag */
-    boolean_t                   b_error;                         /* deadlock */
-    vlc_thread_t                thread_id;        /* id for thread functions */
-    vlc_mutex_t                 programs_lock; /* programs modification lock */
-    vlc_mutex_t                 es_lock;             /* es modification lock */
-    int *                       pi_status;          /* temporary status flag */
-
-    /* Input method description */
-    int                         i_method;                    /* input method */
-    int                         i_handle;          /* file/socket descriptor */
-    char *                      p_source;                          /* source */
-    int                         i_port;                       /* port number */
-    int                         i_vlan;                /* id for vlan method */
-    input_open_t *              p_Open;              /* opener of the method */
-    input_read_t *              p_Read;                  /* reading function */
-    input_close_t *             p_Close;              /* destroying function */
-
-    /* General stream description */
-    stream_descriptor_t *   p_stream;                          /* PAT tables */
-    es_descriptor_t         p_es[INPUT_MAX_ES];/* carried elementary streams */
-    pcr_descriptor_t *      p_pcr;    /* PCR struct used for synchronisation */
-
-    /* List of streams to demux */
-    es_descriptor_t *       pp_selected_es[INPUT_MAX_SELECTED_ES];
-
-    /* Netlists */
-    input_netlist_t         netlist;                            /* see above */
-
-    /* Default settings for spawned decoders */
-    p_aout_thread_t             p_aout;     /* audio output thread structure */
-    p_vout_thread_t             p_vout;               /* video output thread */
-
-#ifdef STATS
-    /* Statistics */
-    count_t                     c_loops;                  /* number of loops */
-    count_t                     c_bytes;                       /* bytes read */
-    count_t                     c_payload_bytes;     /* payload useful bytes */
-    count_t                     c_packets_read;              /* packets read */
-    count_t                     c_packets_trashed;        /* trashed packets */
-#endif
-} input_thread_t;
-
-/* Input methods */
-#define INPUT_METHOD_NONE           0            /* input thread is inactive */
-#define INPUT_METHOD_TS_FILE       10       /* TS stream is read from a file */
-#define INPUT_METHOD_TS_UCAST      20                      /* TS UDP unicast */
-#define INPUT_METHOD_TS_MCAST      21                    /* TS UDP multicast */
-#define INPUT_METHOD_TS_BCAST      22                    /* TS UDP broadcast */
-#define INPUT_METHOD_TS_VLAN_BCAST 32         /* TS UDP broadcast with VLANs */
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-input_thread_t *input_CreateThread      ( int i_method, void *p_source, int i_port,
-                                          int i_vlan, p_vout_thread_t p_vout,
-                                          p_aout_thread_t p_aout, int *pi_status );
-void            input_DestroyThread     ( input_thread_t *p_input, int *pi_status );
-
-
-int             input_OpenAudioStream   ( input_thread_t *p_input, int i_pid );
-void            input_CloseAudioStream  ( input_thread_t *p_input, int i_pid );
-int             input_OpenVideoStream   ( input_thread_t *p_input, int i_pid );
-void            input_CloseVideoStream  ( input_thread_t *p_input, int i_pid );
diff --git a/include/input_ext-dec.h b/include/input_ext-dec.h
new file mode 100644 (file)
index 0000000..40fecfd
--- /dev/null
@@ -0,0 +1,459 @@
+/* Structures exported to the decoders */
+
+/*****************************************************************************
+ * data_packet_t
+ *****************************************************************************
+ * Describe a data packet.
+ *****************************************************************************/
+typedef struct data_packet_s
+{
+    /* Nothing before this line, the code relies on that */
+    byte_t *                p_buffer;                     /* raw data packet */
+
+    /* Decoders information */
+    byte_t *                p_payload_start;
+                                  /* start of the PES payload in this packet */
+    byte_t *                p_payload_end;                    /* guess ? :-) */
+    boolean_t               b_discard_payload;  /* is the packet messed up ? */
+
+    /* Used to chain the TS packets that carry data for a same PES or PSI */
+    struct data_packet_s *  p_next;
+} data_packet_t;
+
+/*****************************************************************************
+ * pes_packet_t
+ *****************************************************************************
+ * Describes an PES packet, with its properties, and pointers to the TS packets
+ * containing it.
+ *****************************************************************************/
+typedef struct pes_packet_s
+{
+    /* PES properties */
+    boolean_t               b_messed_up;  /* At least one of the data packets
+                                           * has a questionable content      */
+    boolean_t               b_data_alignment;  /* used to find the beginning of
+                                                * a video or audio unit      */
+    boolean_t               b_discontinuity; /* This packet doesn't follow the
+                                              * previous one                 */
+
+    boolean_t               b_has_pts;       /* is the following field set ? */
+    mtime_t                 i_pts; /* the PTS for this packet (if set above) */
+
+    int                     i_pes_size;    /* size of the current PES packet */
+
+    /* Pointers to packets (packets are then linked by the p_prev and
+       p_next fields of the data_packet_t struct) */
+    data_packet_t *         p_first;      /* The first packet containing this
+                                           * PES (used by decoders). */
+} pes_packet_t;
+
+/*****************************************************************************
+ * decoder_fifo_t
+ *****************************************************************************
+ * This rotative FIFO contains PES packets that are to be decoded.
+ *****************************************************************************/
+typedef struct decoder_fifo_s
+{
+    /* Thread structures */
+    vlc_mutex_t             data_lock;                     /* fifo data lock */
+    vlc_cond_t              data_wait;     /* fifo data conditional variable */
+
+    /* Data */
+    pes_packet_t *          buffer[FIFO_SIZE + 1];
+    int                     i_start;
+    int                     i_end;
+
+    /* Communication interface between input and decoders */
+    boolean_t               b_die;          /* the decoder should return now */
+    void *                  p_packets_mgt;   /* packets management services
+                                              * data (netlist...)            */
+    void                 (* pf_delete_pes)( void *, pes_packet_t * );
+                                     /* function to use when releasing a PES */
+} decoder_fifo_t;
+
+/* Macros to manage a decoder_fifo_t structure. Please remember to take
+ * data_lock before using them. */
+#define DECODER_FIFO_ISEMPTY( fifo )  ( (fifo).i_start == (fifo).i_end )
+#define DECODER_FIFO_ISFULL( fifo )   ( ( ((fifo).i_end + 1 - (fifo).i_start)\
+                                          & FIFO_SIZE ) == 0 )
+#define DECODER_FIFO_START( fifo )    ( (fifo).buffer[ (fifo).i_start ] )
+#define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
+                                                         & FIFO_SIZE )
+#define DECODER_FIFO_END( fifo )      ( (fifo).buffer[ (fifo).i_end ] )
+#define DECODER_FIFO_INCEND( fifo )   ( (fifo).i_end = ((fifo).i_end + 1) \
+                                                       & FIFO_SIZE )
+
+/*****************************************************************************
+ * bit_fifo_t : bit fifo descriptor
+ *****************************************************************************
+ * This type describes a bit fifo used to store bits while working with the
+ * input stream at the bit level.
+ *****************************************************************************/
+typedef u32         WORD_TYPE;        /* only u32 is supported at the moment */
+
+typedef struct bit_fifo_s
+{
+    /* This unsigned integer allows us to work at the bit level. This buffer
+     * can contain 32 bits, and the used space can be found on the MSb's side
+     * and the available space on the LSb's side. */
+    WORD_TYPE           buffer;
+
+    /* Number of bits available in the bit buffer */
+    int                 i_available;
+
+} bit_fifo_t;
+
+/*****************************************************************************
+ * bit_stream_t : bit stream descriptor
+ *****************************************************************************
+ * This type, based on a PES stream, includes all the structures needed to
+ * handle the input stream like a bit stream.
+ *****************************************************************************/
+typedef struct bit_stream_s
+{
+    /*
+     * Input structures
+     */
+    /* The decoder fifo contains the data of the PES stream */
+    decoder_fifo_t *        p_decoder_fifo;
+
+    /* Function to jump to the next data packet */
+    void                 (* pf_next_data_packet)( struct bit_stream_s * );
+
+    /*
+     * Byte structures
+     */
+    /* Current data packet (in the current PES packet of the PES stream) */
+    data_packet_t *         p_data;
+    /* Pointer to the next byte that is to be read (in the current TS packet) */
+    byte_t *                p_byte;
+    /* Pointer to the last byte that is to be read (in the current TS packet */
+    byte_t *                p_end;
+
+    /*
+     * Bit structures
+     */
+    bit_fifo_t              fifo;
+} bit_stream_t;
+
+/*****************************************************************************
+ * Inline functions used by the decoders to read bit_stream_t
+ *****************************************************************************/
+
+/*
+ * Philosophy of the first implementation : the bit buffer is first filled by
+ * NeedBits, then the buffer can be read via p_bit_stream->fifo.buffer, and
+ * unnecessary bits are dumped with a DumpBits() call.
+ */
+
+/*****************************************************************************
+ * GetByte : reads the next byte in the input stream
+ *****************************************************************************/
+static __inline__ byte_t GetByte( bit_stream_t * p_bit_stream )
+{
+    /* Are there some bytes left in the current data packet ? */
+    /* could change this test to have a if (! (bytes--)) instead */
+    if ( p_bit_stream->p_byte >= p_bit_stream->p_end )
+    {
+        /* no, switch to next data packet */
+        p_bit_stream->pf_next_data_packet( p_bit_stream );
+    }
+
+    return( *(p_bit_stream->p_byte++) );
+}
+
+/*****************************************************************************
+ * NeedBits : reads i_bits new bits in the bit stream and stores them in the
+ *            bit buffer
+ *****************************************************************************
+ * - i_bits must be less or equal 32 !
+ * - There is something important to notice with that function : if the number
+ * of bits available in the bit buffer when calling NeedBits() is greater than
+ * 24 (i_available > 24) but less than the number of needed bits
+ * (i_available < i_bits), the byte returned by GetByte() will be shifted with
+ * a negative value and the number of bits available in the bit buffer will be
+ * set to more than 32 !
+ *****************************************************************************/
+static __inline__ void NeedBits( bit_stream_t * p_bit_stream, int i_bits )
+{
+    while ( p_bit_stream->fifo.i_available < i_bits )
+    {
+        p_bit_stream->fifo.buffer |= ((WORD_TYPE)GetByte( p_bit_stream ))
+                                     << (sizeof(WORD_TYPE) - 8
+                                            - p_bit_stream->fifo.i_available);
+        p_bit_stream->fifo.i_available += 8;
+    }
+}
+
+/*****************************************************************************
+ * DumpBits : removes i_bits bits from the bit buffer
+ *****************************************************************************
+ * - i_bits <= i_available
+ * - i_bits < 32 (because (u32 << 32) <=> (u32 = u32))
+ *****************************************************************************/
+static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int i_bits )
+{
+    p_bit_stream->fifo.buffer <<= i_bits;
+    p_bit_stream->fifo.i_available -= i_bits;
+}
+
+
+/*
+ * Philosophy of the second implementation : WORD_LENGTH (usually 32) bits
+ * are read at the same time, thus minimizing the number of p_byte changes.
+ * Bits are read via GetBits() or ShowBits. This is slightly faster. Be
+ * aware that if, in the forthcoming functions, i_bits > 24, the data have to
+ * be already aligned on an 8-bit boundary, or wrong results will be
+ * returned.
+ */
+
+#if (WORD_TYPE != u32)
+#   error Not supported word
+#endif
+
+/*
+ * This is stolen from the livid source who stole it from the kernel
+ * FIXME: The macro swab32 for little endian machines does
+ *        not seem to work correctly
+ */
+
+#if defined(SYS_BEOS)
+#   define swab32(x) B_BENDIAN_TO_HOST_INT32(x)
+#else
+#   if __BYTE_ORDER == __BIG_ENDIAN
+#       define swab32(x) (x)
+#   else
+#       if defined (__i386__)
+static __inline__ const u32 __i386_swab32( u32 x )
+{
+    __asm__("bswap %0" : "=r" (x) : "0" (x));
+    return x;
+}
+#           define swab32(x) __i386_swab32(x)
+#       else
+#           define swab32(x)                                                 \
+            ( ( (u32)(((u8*)&x)[0]) << 24 ) | ( (u32)(((u8*)&x)[1]) << 16 ) |\
+              ( (u32)(((u8*)&x)[2]) << 8 )  | ( (u32)(((u8*)&x)[3])) )
+#       endif
+#   endif
+#endif
+
+/*****************************************************************************
+ * ShowBits : return i_bits bits from the bit stream
+ *****************************************************************************/
+static __inline__ WORD_TYPE ShowWord( bit_stream_t * p_bit_stream )
+{
+    if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
+    {
+        return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
+    }
+
+    p_bit_stream->pf_next_data_packet( p_bit_stream );
+    return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
+}
+
+static __inline__ WORD_TYPE ShowBits( bit_stream_t * p_bit_stream, int i_bits )
+{
+    if( p_bit_stream->fifo.i_available >= i_bits )
+    {
+        return( p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - i_bits) );
+    }
+
+    return( (p_bit_stream->fifo.buffer |
+            (ShowWord( p_bit_stream ) >> p_bit_stream->fifo.i_available))
+                    >> (8 * sizeof(WORD_TYPE) - i_bits) );
+}
+
+/*****************************************************************************
+ * GetWord : returns the next word to be read
+ *****************************************************************************/
+static __inline__ WORD_TYPE GetWord( bit_stream_t * p_bit_stream )
+{
+    if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
+    {
+        return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
+    }
+    else
+    {
+        p_bit_stream->pf_next_data_packet( p_bit_stream );
+        return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
+    }
+}
+
+/*****************************************************************************
+ * RemoveBits : removes i_bits bits from the bit buffer
+ *****************************************************************************/
+static __inline__ void RemoveBits( bit_stream_t * p_bit_stream, int i_bits )
+{
+    p_bit_stream->fifo.i_available -= i_bits;
+
+    if( p_bit_stream->fifo.i_available >= 0 )
+    {
+        p_bit_stream->fifo.buffer <<= i_bits;
+        return;
+    }
+    p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
+                            << ( -p_bit_stream->fifo.i_available );
+    p_bit_stream->fifo.i_available += sizeof(WORD_TYPE) * 8;
+}
+
+/*****************************************************************************
+ * RemoveBits32 : removes 32 bits from the bit buffer (and as a side effect,
+ *                refill it). This should be faster than RemoveBits, though
+ *                RemoveBits will work, too.
+ *****************************************************************************/
+static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
+{
+    p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
+                        << (32 - p_bit_stream->fifo.i_available);
+}
+
+/*****************************************************************************
+ * GetBits : returns i_bits bits from the bit stream and removes them
+ *****************************************************************************/
+static __inline__ WORD_TYPE GetBits( bit_stream_t * p_bit_stream, int i_bits )
+{
+    u32             i_result;
+
+    p_bit_stream->fifo.i_available -= i_bits;
+    if( p_bit_stream->fifo.i_available >= 0 )
+    {
+        i_result = p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - i_bits);
+        p_bit_stream->fifo.buffer <<= i_bits;
+        return( i_result );
+    }
+
+    i_result = p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - i_bits);
+    p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
+    i_result |= p_bit_stream->fifo.buffer
+                             >> (8 * sizeof(WORD_TYPE)
+                                     + p_bit_stream->fifo.i_available);
+    p_bit_stream->fifo.buffer <<= ( -p_bit_stream->fifo.i_available );
+    p_bit_stream->fifo.i_available += sizeof(WORD_TYPE) * 8;
+
+    return( i_result );
+}
+
+/*****************************************************************************
+ * GetBits32 : returns 32 bits from the bit stream and removes them
+ *****************************************************************************/
+static __inline__ WORD_TYPE GetBits32( bit_stream_t * p_bit_stream )
+{
+    WORD_TYPE               i_result;
+
+    i_result = p_bit_stream->fifo.buffer;
+    p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
+    i_result |= p_bit_stream->fifo.buffer
+                             >> (p_bit_stream->fifo.i_available);
+    p_bit_stream->fifo.buffer <<= (8 * sizeof(WORD_TYPE)
+                                    - p_bit_stream->fifo.i_available);
+    
+    return( i_result );
+}
+
+/*****************************************************************************
+ * RealignBits : realigns the bit buffer on an 8-bit boundary
+ *****************************************************************************/
+static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
+{
+    p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
+    p_bit_stream->fifo.i_available &= ~0x7;
+}
+
+
+/*
+ * Communication interface between input and decoders
+ */
+
+/*****************************************************************************
+ * decoder_config_t
+ *****************************************************************************
+ * Standard pointers given to the decoders as a toolbox.
+ *****************************************************************************/
+typedef struct decoder_config_s
+{
+    u16                     i_stream_id;
+    u8                      i_type;         /* type of the elementary stream */
+
+    struct stream_ctrl_s *  p_stream_ctrl;
+    struct decoder_fifo_s * p_decoder_fifo;
+    void                 (* pf_init_bit_stream)( struct bit_stream_s *,
+                                                 struct decoder_fifo_s * );
+} decoder_config_t;
+
+/*****************************************************************************
+ * vdec_config_t
+ *****************************************************************************
+ * Pointers given to video decoders threads.
+ *****************************************************************************/
+struct vout_thread_s;
+
+typedef struct vdec_config_s
+{
+    struct vout_thread_s *  p_vout;
+
+    struct picture_s *   (* pf_create_picture)( struct vout_thread_s *,
+                                                int i_type, int i_width,
+                                                int i_height );
+    void                 (* pf_destroy_picture)( struct vout_thread_s *,
+                                                 struct picture_s * );
+    void                 (* pf_display_picture)( struct vout_thread_s *,
+                                                 struct picture_s * );
+    void                 (* pf_date_picture)( struct vout_thread_s *,
+                                              struct picture_s *, mtime_t date );
+    void                 (* pf_link_picture)( struct vout_thread_s *,
+                                              struct picture_s *, mtime_t date );
+    void                 (* pf_unlink_picture)( struct vout_thread_s *,
+                                                struct picture_s *, mtime_t date );
+    struct subpicture_s *(* pf_create_subpicture)( struct vout_thread_s *,
+                                                   int i_type, int i_size );
+    void                 (* pf_destroy_subpicture)( struct vout_thread_s *,
+                                                    struct subpicture_s * );
+    void                 (* pf_display_subpicture)( struct vout_thread_s *,
+                                                    struct subpicture_s * );
+
+    decoder_config_t        decoder_config;
+} vdec_config_t;
+
+/*****************************************************************************
+ * adec_config_t
+ *****************************************************************************
+ * Pointers given to audio decoders threads.
+ *****************************************************************************/
+struct aout_thread_s;
+
+typedef struct adec_config_s
+{
+    struct aout_thread_s *  p_aout;
+
+    struct aout_fifo_s * (* pf_create_fifo)( struct aout_thread_s *,
+                                            struct aout_fifo_s * );
+    void                 (* pf_destroy_fifo)( struct aout_thread_s *);
+
+    decoder_config_t        decoder_config;
+} adec_config_t;
+
+
+/*
+ * Communication interface between decoders and input
+ */
+
+/*****************************************************************************
+ * decoder_capabilities_t
+ *****************************************************************************
+ * Structure returned by a call to GetCapabilities() of the decoder.
+ *****************************************************************************/
+typedef struct decoder_capabilities_s
+{
+    int                     i_dec_type;
+    u8                      i_stream_type;   /* == i_type in es_descriptor_t */
+    int                     i_weight; /* for a given stream type, the decoder
+                                       * with higher weight will be spawned  */
+
+    vlc_thread_t         (* pf_create_thread)( struct decoder_config_s * );
+} decoder_capabilities_t;
+
+/* Decoder types */
+#define NONE_D              0
+#define VIDEO_D             1
+#define AUDIO_D             2
diff --git a/include/input_ext-intf.h b/include/input_ext-intf.h
new file mode 100644 (file)
index 0000000..7060fcf
--- /dev/null
@@ -0,0 +1,246 @@
+/* Structures exported to the interface */
+
+/*
+ * Communication input -> interface
+ */
+#define INPUT_MAX_PLUGINS   1
+
+/*****************************************************************************
+ * es_descriptor_t: elementary stream descriptor
+ *****************************************************************************
+ * Describes an elementary stream, and includes fields required to handle and
+ * demultiplex this elementary stream.
+ *****************************************************************************/
+struct decoder_fifo_s;                         /* defined in input_ext-dec.h */
+struct pgrm_descriptor_s;
+
+typedef struct es_descriptor_s
+{
+    u16                     i_id;            /* stream ID for PS, PID for TS */
+    u8                      i_stream_id;     /* stream ID defined in the PES */
+    u8                      i_type;                           /* stream type */
+
+    /* Demultiplexer information */
+    void *                  p_demux_data;
+    struct pgrm_descriptor_s *
+                            p_pgrm;  /* very convenient in the demultiplexer */
+    boolean_t               b_discontinuity;
+
+    /* 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 */
+    struct decoder_fifo_s * p_decoder_fifo;
+    vlc_thread_t            thread_id;                  /* ID of the decoder */
+
+#ifdef STATS
+    count_t                 c_payload_bytes;/* total of payload useful bytes */
+    count_t                 c_packets;                 /* total packets read */
+    count_t                 c_invalid_packets;       /* invalid packets read */
+#endif
+} es_descriptor_t;
+
+/* Special PID values - note that the PID is only on 13 bits, and that values
+ * greater than 0x1fff have no meaning in a stream */
+#define PROGRAM_ASSOCIATION_TABLE_PID   0x0000
+#define CONDITIONNAL_ACCESS_TABLE_PID   0x0001                   /* not used */
+#define EMPTY_ID                        0xffff    /* empty record in a table */
+/* ES streams types - see ISO/IEC 13818-1 table 2-29 numbers */
+#define MPEG1_VIDEO_ES      0x01
+#define MPEG2_VIDEO_ES      0x02
+#define MPEG1_AUDIO_ES      0x03
+#define MPEG2_AUDIO_ES      0x04
+#define AC3_AUDIO_ES        0x81
+#define DVD_SPU_ES          0x82              /* 0x82 might violate the norm */
+#define LPCM_AUDIO_ES       0x83
+
+/*****************************************************************************
+ * pgrm_descriptor_t
+ *****************************************************************************
+ * Describes a program and list associated elementary streams. It is build by
+ * the PSI decoder upon the informations carried in program map sections
+ *****************************************************************************/
+typedef struct pgrm_descriptor_s
+{
+    /* Program characteristics */
+    u16                     i_number;                      /* program number */
+    u8                      i_version;                     /* version number */
+    boolean_t               b_is_ok;      /* Is the description up to date ? */
+
+    /* Service Descriptor (program name) - DVB extension */
+    u8                      i_srv_type;
+    char *                  psz_srv_name;
+
+    /* Synchronization information */
+    /* system_date = PTS_date + delta_cr + delta_absolute */
+    mtime_t                 delta_cr;
+    mtime_t                 delta_absolute;
+    mtime_t                 last_cr;
+    count_t                 c_average_count;
+                           /* counter used to compute dynamic average values */
+    int                     i_synchro_state;
+
+    /* Demultiplexer data */
+    void *                  p_demux_data;
+
+    /* Decoders control */
+    struct vout_thread_s *  p_vout;
+    struct aout_thread_s *  p_aout;
+
+    int                     i_es_number;      /* size of the following array */
+    es_descriptor_t **      pp_es;                /* array of pointers to ES */
+} pgrm_descriptor_t;
+
+/* Synchro states */
+#define SYNCHRO_OK          0
+#define SYNCHRO_NOT_STARTED 1
+#define SYNCHRO_START       2
+#define SYNCHRO_REINIT      3
+
+/*****************************************************************************
+ * stream_descriptor_t
+ *****************************************************************************
+ * Describes a stream and list its associated programs. Build upon
+ * the information carried in program association sections (for instance)
+ *****************************************************************************/
+typedef struct stream_descriptor_s
+{
+    u16                     i_stream_id;                        /* stream id */
+    vlc_mutex_t             stream_lock;  /* to be taken every time you read
+                                           * or modify stream, pgrm or es    */
+
+    /* Input method data */
+    boolean_t               b_pace_control;    /* can we read when we want ? */
+    boolean_t               b_seekable;               /* can we do lseek() ? */
+    /* if (b_seekable) : */
+    off_t                   i_size;     /* total size of the file (in bytes) */
+    off_t                   i_tell;/* actual location in the file (in bytes) */
+
+    /* Demultiplexer data */
+    void *                  p_demux_data;
+
+    /* Programs description */
+    int                     i_pgrm_number;    /* size of the following array */
+    pgrm_descriptor_t **    pp_programs;        /* array of pointers to pgrm */
+
+    /* Stream control */
+    stream_ctrl_t           control;
+} stream_descriptor_t;
+
+/*****************************************************************************
+ * i_p_config_t
+ *****************************************************************************
+ * This structure gives plugins pointers to the useful functions of input
+ *****************************************************************************/
+struct input_thread_s;
+struct data_packet_s;
+struct es_descriptor_s;
+
+typedef struct i_p_config_s
+{
+    int                 (* pf_peek_stream)( struct input_thread_s *,
+                                            byte_t * buffer, size_t );
+    void                (* pf_demux_pes)( struct input_thread_s *,
+                                          struct data_packet_s *,
+                                          struct es_descriptor_s *,
+                                          boolean_t b_unit_start,
+                                          boolean_t b_packet_lost );
+} i_p_config_t;
+
+/*****************************************************************************
+ * input_thread_t
+ *****************************************************************************
+ * This structure includes all the local static variables of an input thread
+ *****************************************************************************/
+struct aout_thread_s;
+struct vout_thread_s;
+
+typedef struct input_thread_s
+{
+    /* Thread properties and locks */
+    boolean_t               b_die;                             /* 'die' flag */
+    boolean_t               b_error;
+    vlc_thread_t            thread_id;            /* id for thread functions */
+    int *                   pi_status;              /* temporary status flag */
+
+    struct input_config_s * p_config;
+
+    struct input_capabilities_s *
+                            pp_plugins[INPUT_MAX_PLUGINS];/* list of plugins */
+    struct input_capabilities_s *
+                            p_plugin;                     /* selected plugin */
+    i_p_config_t            i_p_config;              /* plugin configuration */
+
+    int                     i_handle;           /* socket or file descriptor */
+    void *                  p_method_data;
+
+    /* General stream description */
+    stream_descriptor_t     stream;                            /* PAT tables */
+    es_descriptor_t         p_es[INPUT_MAX_ES];
+                                               /* carried elementary streams */
+
+    /* List of streams to demux */
+    es_descriptor_t *       pp_selected_es[INPUT_MAX_SELECTED_ES];
+
+    /* For auto-launch of decoders */
+    struct aout_thread_s *  p_default_aout;
+    struct vout_thread_s *  p_default_vout;
+
+#ifdef STATS
+    count_t                 c_loops;
+    count_t                 c_bytes;                           /* bytes read */
+    count_t                 c_payload_bytes;         /* payload useful bytes */
+    count_t                 c_packets_read;                  /* packets read */
+    count_t                 c_packets_trashed;            /* trashed packets */
+#endif
+} input_thread_t;
+
+
+/*
+ * Communication interface -> input
+ */
+
+/*****************************************************************************
+ * input_config_t
+ *****************************************************************************
+ * This structure is given by the interface to an input thread
+ *****************************************************************************/
+typedef struct input_config_s
+{
+    /* Input method description */
+    int                         i_method;                    /* input method */
+    char *                      p_source;                          /* source */
+
+    /* For auto-launch of decoders */
+    struct aout_thread_s *      p_default_aout;
+    struct vout_thread_s *      p_default_vout;
+} input_config_t;
+
+/* Input methods */
+#define INPUT_METHOD_NONE           0            /* input thread is inactive */
+#define INPUT_METHOD_FILE          10   /* stream is read from file p_source */
+#define INPUT_METHOD_UCAST         20                         /* UDP unicast */
+#define INPUT_METHOD_MCAST         21                       /* UDP multicast */
+#define INPUT_METHOD_BCAST         22                       /* UDP broadcast */
+#define INPUT_METHOD_VLAN_BCAST    32            /* UDP broadcast with VLANs */
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+struct input_thread_s * input_CreateThread( struct input_config_s *,
+                                            int *pi_status );
+void                    input_DestroyThread( struct input_thread_s *,
+                                             int *pi_status );
+void                    input_PauseProgram( struct input_thread_s *,
+                                            struct pgrm_descriptor_s * );
+void                    input_PlayProgram( struct input_thread_s *,
+                                           struct pgrm_descriptor_s * );
+void                    input_FFProgram( struct input_thread_s *,
+                                         struct pgrm_descriptor_s * );
+void                    input_SMProgram( struct input_thread_s *,
+                                           struct pgrm_descriptor_s * );
+void                    input_RewindProgram( struct input_thread_s *,
+                                             struct pgrm_descriptor_s * );
diff --git a/include/input_netlist.h b/include/input_netlist.h
deleted file mode 100644 (file)
index 3387b62..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*****************************************************************************
- * input_netlist.h: netlist interface
- * The netlists are an essential part of the input structure. We maintain a
- * list of free TS packets and free PES packets to avoid continuous malloc
- * and free.
- *****************************************************************************
- * Copyright (C) 1998, 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-#include "intf_msg.h"
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int     input_NetlistInit       ( input_thread_t *p_input );
-void    input_NetlistEnd        ( input_thread_t *p_input );
-
-static __inline__ void input_NetlistFreePES( input_thread_t *p_input, pes_packet_t *p_pes_packet );
-static __inline__ void input_NetlistFreeTS( input_thread_t *p_input, ts_packet_t *p_ts_packet );
-static __inline__ pes_packet_t* input_NetlistGetPES( input_thread_t *p_input );
-
-/*****************************************************************************
- * input_NetlistFreePES: add a PES packet to the netlist
- *****************************************************************************
- * Add a PES packet to the PES netlist, so that the packet can immediately be
- * reused by the demultiplexer. We put this function directly in the .h file,
- * because it is very frequently called.
- *****************************************************************************/
-static __inline__ void input_NetlistFreePES( input_thread_t *p_input,
-                                  pes_packet_t *p_pes_packet )
-{
-    int             i_dummy;
-    ts_packet_t *   p_ts_packet;
-
-    ASSERT(p_pes_packet);
-
-    /* We will be playing with indexes, so we take a lock. */
-    vlc_mutex_lock( &p_input->netlist.lock );
-
-    /* Free all TS packets in this PES structure. */
-    p_ts_packet = p_pes_packet->p_first_ts;
-    for( i_dummy = 0; i_dummy < p_pes_packet->i_ts_packets; i_dummy++ )
-    {
-        ASSERT(p_ts_packet);
-
-#ifdef INPUT_LIFO_TS_NETLIST
-        p_input->netlist.i_ts_index--;
-        p_input->netlist.p_ts_free[p_input->netlist.i_ts_index].iov_base
-                             = (void *)p_ts_packet;
-#else /* FIFO */
-        p_input->netlist.p_ts_free[p_input->netlist.i_ts_end].iov_base
-                             = (void *)p_ts_packet;
-        p_input->netlist.i_ts_end++;
-        p_input->netlist.i_ts_end &= INPUT_MAX_TS; /* loop */
-#endif
-        p_ts_packet = p_ts_packet->p_next_ts;
-    }
-
-    /* Free the PES structure. */
-#ifdef INPUT_LIFO_PES_NETLIST
-    p_input->netlist.i_pes_index--;
-    p_input->netlist.p_pes_free[p_input->netlist.i_pes_index] = p_pes_packet;
-#else /* FIFO */
-    p_input->netlist.p_pes_free[p_input->netlist.i_pes_end] = p_pes_packet;
-    p_input->netlist.i_pes_end++;
-    p_input->netlist.i_pes_end &= INPUT_MAX_PES; /* loop */
-#endif
-
-    vlc_mutex_unlock( &p_input->netlist.lock );
-}
-
-/*****************************************************************************
- * input_NetlistFreeTS: add a TS packet to the netlist
- *****************************************************************************
- * Add a TS packet to the TS netlist, so that the packet can immediately be
- * reused by the demultiplexer. Shouldn't be called by other threads (they
- * should only use input_FreePES.
- *****************************************************************************/
-static __inline__ void input_NetlistFreeTS( input_thread_t *p_input,
-                                            ts_packet_t *p_ts_packet )
-{
-    ASSERT(p_ts_packet);
-
-    /* We will be playing with indexes, so we take a lock. */
-    vlc_mutex_lock( &p_input->netlist.lock );
-
-    /* Free the TS structure. */
-#ifdef INPUT_LIFO_TS_NETLIST
-    p_input->netlist.i_ts_index--;
-    p_input->netlist.p_ts_free[p_input->netlist.i_ts_index].iov_base
-        = (void *)p_ts_packet;
-#else /* FIFO */
-    p_input->netlist.p_ts_free[p_input->netlist.i_ts_end].iov_base
-        = (void *)p_ts_packet;
-    p_input->netlist.i_ts_end++;
-    p_input->netlist.i_ts_end &= INPUT_MAX_TS; /* loop */
-#endif
-
-    vlc_mutex_unlock( &p_input->netlist.lock );
-}
-
-/*****************************************************************************
- * input_NetlistGetPES: remove a PES packet from the netlist
- *****************************************************************************
- * Add a TS packet to the TS netlist, so that the packet can immediately be
- * reused by the demultiplexer. Shouldn't be called by other threads (they
- * should only use input_FreePES.
- *****************************************************************************/
-static __inline__ pes_packet_t* input_NetlistGetPES( input_thread_t *p_input )
-{
-    pes_packet_t *          p_pes_packet;
-
-#ifdef INPUT_LIFO_PES_NETLIST
-    /* i_pes_index might be accessed by a decoder thread to give back a
-     * packet. */
-    vlc_mutex_lock( &p_input->netlist.lock );
-
-    /* Verify that we still have PES packet in the netlist */
-    if( (INPUT_MAX_PES - p_input->netlist.i_pes_index ) <= 1 )
-    {
-        intf_ErrMsg("input error: PES netlist is empty !\n");
-        return( NULL );
-    }
-
-    /* Fetch a new PES packet */
-    p_pes_packet = p_input->netlist.p_pes_free[p_input->netlist.i_pes_index];
-    p_input->netlist.i_pes_index++;
-    vlc_mutex_unlock( &p_input->netlist.lock );
-
-#else /* FIFO */
-    /* No need to lock, since we are the only ones accessing i_pes_start. */
-
-    /* Verify that we still have PES packet in the netlist */
-    if( ((p_input->netlist.i_pes_end -1 - p_input->netlist.i_pes_start) & INPUT_MAX_PES) <= 1 )
-    {
-        intf_ErrMsg("input error: PES netlist is empty !\n");
-        return( NULL );
-    }
-
-    p_pes_packet = p_input->netlist.p_pes_free[p_input->netlist.i_pes_start];
-    p_input->netlist.i_pes_start++;
-    p_input->netlist.i_pes_start &= INPUT_MAX_PES; /* loop */
-#endif /* netlist type */
-
-    /* Initialize PES flags. */
-    p_pes_packet->b_data_loss = 0;
-    p_pes_packet->b_data_alignment = 0;
-    p_pes_packet->b_has_pts = 0;
-    p_pes_packet->b_random_access = 0;
-    p_pes_packet->b_discard_payload = 0;
-    p_pes_packet->i_pes_size = 0;
-    p_pes_packet->i_pes_real_size = 0;
-    p_pes_packet->i_ts_packets = 0;
-    p_pes_packet->p_first_ts = NULL;
-    p_pes_packet->p_last_ts = NULL;
-
-    return( p_pes_packet );
-}
diff --git a/include/input_ps.h b/include/input_ps.h
deleted file mode 100644 (file)
index 87782c0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*****************************************************************************
- * input_file.h: file input method
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
- *          Samuel Hocevar <sam@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-
-#define REQUESTED_AC3          0
-#define REQUESTED_MPEG         1
-#define REQUESTED_LPCM         2
-#define REQUESTED_NOAUDIO    255
-
diff --git a/include/stream_control.h b/include/stream_control.h
new file mode 100644 (file)
index 0000000..92f76bf
--- /dev/null
@@ -0,0 +1,28 @@
+/* Structures exported to interface, input and decoders */
+
+/*****************************************************************************
+ * stream_ctrl_t
+ *****************************************************************************
+ * Describe the state of a program stream.
+ *****************************************************************************/
+typedef struct stream_ctrl_s
+{
+    vlc_mutex_t             control_lock;
+
+    int                     i_status;
+    /* if i_status == FORWARD_S or BACKWARD_S */
+    int                     i_rate;
+    s64                     i_ref_sysdate;
+    s64                     i_ref_clock;
+
+    boolean_t               b_mute;
+    boolean_t               b_bw;                           /* black & white */
+} stream_ctrl_t;
+
+/* Possible status : */
+#define PLAYING_S           0
+#define PAUSE_S             1
+#define FORWARD_S           2
+#define BACKWARD_S          3
+
+#define DEFAULT_RATE        1000
index a865d63671f296a9d5512edb8b87126a1b2941b7..71ad4acea072c2aa3c260c1611662aaa05e88afc 100644 (file)
@@ -95,10 +95,10 @@ typedef struct vpar_thread_s
 
 
     /* Input properties */
-    decoder_fifo_t      fifo;                              /* PES input fifo */
-
-    /* The bit stream structure handles the PES stream at the bit level */
+    decoder_fifo_t *    p_fifo;                            /* PES input fifo */
     bit_stream_t        bit_stream;
+    vdec_config_t *     p_config;
+
 
     /* Output properties */
     vout_thread_t *     p_vout;                       /* video output thread */
@@ -151,28 +151,20 @@ typedef struct vpar_thread_s
  *****************************************************************************/
 
 /* Thread management functions */
-vpar_thread_t * vpar_CreateThread       ( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
-                                          vout_thread_t *p_vout, int *pi_status */ );
-void            vpar_DestroyThread      ( vpar_thread_t *p_vpar /*, int *pi_status */ );
-
-/* Time management functions */
-/* XXX?? */
-
-/* Dynamic thread settings */
-/* XXX?? */
-
+vlc_thread_t vpar_CreateThread       ( vdec_config_t * );
 
 /*****************************************************************************
  * NextStartCode : Find the next start code
  *****************************************************************************/
-static __inline__ void NextStartCode( vpar_thread_t * p_vpar )
+static __inline__ void NextStartCode( bit_stream_t * p_bit_stream )
 {
     /* Re-align the buffer on an 8-bit boundary */
-    RealignBits( &p_vpar->bit_stream );
+    RealignBits( p_bit_stream );
 
-    while( ShowBits( &p_vpar->bit_stream, 24 ) != 0x01L && !p_vpar->b_die )
+    while( ShowBits( p_bit_stream, 24 ) != 0x01L
+            && !p_bit_stream->p_decoder_fifo->b_die )
     {
-        RemoveBits( &p_vpar->bit_stream, 8 );
+        RemoveBits( p_bit_stream, 8 );
     }
 }
 
index 911c0eec3e2315031fcd7a6bde370cdc63277902..00d45454cda1d4c868d63e15e79749b32fea09c2 100644 (file)
@@ -26,8 +26,6 @@
 #include "defs.h"
 
 #include <stdlib.h>                                      /* malloc(), free() */
-#include <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
 
 #include "config.h"
 #include "common.h"
@@ -35,7 +33,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index bb1ef6640f564a5506b2d39d7a085e91598d51f4..ee0788d9b9464924f0c6171445084773d5ff0863 100644 (file)
@@ -44,7 +44,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index cb50e87b97434ac557b1637c332aaa283a61a3e6..53e68969bab75122e68113f0a515907958ddb332 100644 (file)
@@ -42,7 +42,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index c4bc5211e7554f06db42342be6ec3c7013c4c0e7..a42a3749608f7e965c85004cca154096322ac785 100644 (file)
@@ -36,7 +36,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index b470090f43189699b4abe19f2bb1a9b5f09570e6..3ce80c6ff957f97ab30387155234730495c16991 100644 (file)
@@ -41,7 +41,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index 8f560ff70e8226293f5b27d59e8b939fcf541271..b257030d654606e1c5432d56eaa661c527e29f56 100644 (file)
@@ -41,7 +41,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index aaaeb6e1c5157e2fac658881d25ab5815536fd67..16ee73b3d4e2e4df3ed1f47197ce604766506123 100644 (file)
@@ -38,7 +38,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index 261faf2c22713aff40024620e35693b67bdda7a4..809a11b2dc159661f98057b89ef377634627f09f 100644 (file)
@@ -41,7 +41,9 @@
 #include "mtime.h"
 #include "plugins.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
+
 #include "video.h"
 #include "video_output.h"
 
index cf6f1c76abd794b15446d53d850fa112fa611b95..29be71cb203453c76cd31738d272fa209acd9b52 100644 (file)
@@ -50,9 +50,8 @@
 
 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
 
-#include "input.h"                                           /* pes_packet_t */
-#include "input_netlist.h"                         /* input_NetlistFreePES() */
-#include "decoder_fifo.h"         /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
+#include "stream_control.h"
+#include "input_ext-dec.h"
 
 #include "audio_output.h"
 
@@ -72,7 +71,7 @@ static void     EndThread               (ac3dec_thread_t * p_adec);
 /*****************************************************************************
  * ac3dec_CreateThread: creates an ac3 decoder thread
  *****************************************************************************/
-ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
+vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
 {
     ac3dec_thread_t *   p_ac3dec;
 
@@ -83,7 +82,7 @@ ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
     {
         intf_ErrMsg ( "ac3dec error: not enough memory "
                       "for ac3dec_CreateThread() to create the new thread\n");
-        return NULL;
+        return 0;
     }
 
     /*
@@ -91,27 +90,16 @@ ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
      */
     p_ac3dec->b_die = 0;
     p_ac3dec->b_error = 0;
-
-    /*
-     * Initialize the input properties
-     */
-    /* Initialize the decoder fifo's data lock and conditional variable and set
-     * its buffer as empty */
-    vlc_mutex_init (&p_ac3dec->fifo.data_lock);
-    vlc_cond_init (&p_ac3dec->fifo.data_wait);
-    p_ac3dec->fifo.i_start = 0;
-    p_ac3dec->fifo.i_end = 0;
+    p_ac3dec->p_config = p_config;
+    p_ac3dec->p_fifo = p_config->decoder_config.p_decoder_fifo;
 
     /* Initialize the ac3 decoder structures */
     ac3_init (&p_ac3dec->ac3_decoder);
 
-    /* Initialize the bit stream structure */
-    p_ac3dec->p_input = p_input;
-
     /*
      * Initialize the output properties
      */
-    p_ac3dec->p_aout = p_input->p_aout;
+    p_ac3dec->p_aout = p_config->p_aout;
     p_ac3dec->p_aout_fifo = NULL;
 
     /* Spawn the ac3 decoder thread */
@@ -119,31 +107,11 @@ ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
     {
         intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread\n" );
         free (p_ac3dec);
-        return NULL;
+        return 0;
     }
 
     intf_DbgMsg ("ac3dec debug: ac3 decoder thread (%p) created\n", p_ac3dec);
-    return p_ac3dec;
-}
-
-/*****************************************************************************
- * ac3dec_DestroyThread: destroys an ac3 decoder thread
- *****************************************************************************/
-void ac3dec_DestroyThread (ac3dec_thread_t * p_ac3dec)
-{
-    intf_DbgMsg ("ac3dec debug: requesting termination of ac3 decoder thread %p\n", p_ac3dec);
-
-    /* Ask thread to kill itself */
-    p_ac3dec->b_die = 1;
-
-    /* Make sure the decoder thread leaves the GetByte() function */
-    vlc_mutex_lock (&(p_ac3dec->fifo.data_lock));
-    vlc_cond_signal (&(p_ac3dec->fifo.data_wait));
-    vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
-
-    /* Waiting for the decoder thread to exit */
-    /* Remove this as soon as the "status" flag is implemented */
-    vlc_thread_join (p_ac3dec->thread_id);
+    return p_ac3dec->thread_id;
 }
 
 /* Following functions are local */
@@ -158,26 +126,12 @@ static int InitThread (ac3dec_thread_t * p_ac3dec)
 
     intf_DbgMsg ("ac3dec debug: initializing ac3 decoder thread %p\n", p_ac3dec);
 
-    /* Our first job is to initialize the bit stream structure with the
-     * beginning of the input stream */
-    vlc_mutex_lock (&p_ac3dec->fifo.data_lock);
-    while (DECODER_FIFO_ISEMPTY(p_ac3dec->fifo))
-    {
-        if (p_ac3dec->b_die)
-        {
-            vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
-            return -1;
-        }
-        vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock);
-    }
-    p_ac3dec->p_ts = DECODER_FIFO_START (p_ac3dec->fifo)->p_first_ts;
+    p_ac3dec->p_data = DECODER_FIFO_START(*p_ac3dec->p_fifo)->p_first;
     byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder);
-    byte_stream->p_byte =
-        p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start;
-    byte_stream->p_end =
-        p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end;
+    byte_stream->p_byte = p_ac3dec->p_data->p_payload_start;
+    byte_stream->p_end = p_ac3dec->p_data->p_payload_end;
     byte_stream->info = p_ac3dec;
-    vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
+    vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
 
     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
     aout_fifo.i_channels = 2;
@@ -204,7 +158,8 @@ static void RunThread (ac3dec_thread_t * p_ac3dec)
 
     intf_DbgMsg ("ac3dec debug: running ac3 decoder thread (%p) (pid == %i)\n", p_ac3dec, getpid());
 
-    msleep (INPUT_PTS_DELAY);
+    /* FIXME ! Qu'est-ce que c'est que ce bordel !?!?!?!? --Meuuh */
+    //msleep (INPUT_PTS_DELAY);
 
     /* Initializing the ac3 decoder thread */
     if (InitThread (p_ac3dec)) /* XXX?? */
@@ -264,10 +219,10 @@ static void RunThread (ac3dec_thread_t * p_ac3dec)
             p_ac3dec->sync_ptr = 0;
         }
 
-        if (DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts)
+        if (DECODER_FIFO_START(*p_ac3dec->p_fifo)->b_has_pts)
         {
-            p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_ac3dec->fifo)->i_pts;
-            DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts = 0;
+            p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_ac3dec->p_fifo)->i_pts;
+            DECODER_FIFO_START(*p_ac3dec->p_fifo)->b_has_pts = 0;
         }
         else
         {
@@ -315,24 +270,26 @@ static void ErrorThread (ac3dec_thread_t * p_ac3dec)
 {
     /* We take the lock, because we are going to read/write the start/end
      * indexes of the decoder fifo */
-    vlc_mutex_lock (&p_ac3dec->fifo.data_lock);
+    vlc_mutex_lock (&p_ac3dec->p_fifo->data_lock);
 
     /* Wait until a `die' order is sent */
     while (!p_ac3dec->b_die)
     {
         /* Trash all received PES packets */
-        while (!DECODER_FIFO_ISEMPTY(p_ac3dec->fifo))
+        while (!DECODER_FIFO_ISEMPTY(*p_ac3dec->p_fifo))
         {
-            input_NetlistFreePES (p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo));
-            DECODER_FIFO_INCSTART (p_ac3dec->fifo);
+            p_ac3dec->p_fifo->pf_delete_pes(p_ac3dec->p_fifo->p_packets_mgt,
+                    DECODER_FIFO_START(*p_ac3dec->p_fifo));
+            DECODER_FIFO_INCSTART (*p_ac3dec->p_fifo);
         }
 
         /* Waiting for the input thread to put new PES packets in the fifo */
-        vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock);
+        vlc_cond_wait (&p_ac3dec->p_fifo->data_wait,
+                       &p_ac3dec->p_fifo->data_lock);
     }
 
     /* We can release the lock before leaving */
-    vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
+    vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
 }
 
 /*****************************************************************************
@@ -369,19 +326,19 @@ void ac3_byte_stream_next (ac3_byte_stream_t * p_byte_stream)
     {
         /* We were reading the last TS packet of this PES packet... It's
          * time to jump to the next PES packet */
-        if (p_ac3dec->p_ts->p_next_ts == NULL)
+        if (p_ac3dec->p_data->p_next == NULL)
         {
             int ptr;
 
             /* We are going to read/write the start and end indexes of the 
              * decoder fifo and to use the fifo's conditional variable, 
              * that's why we need to take the lock before */ 
-            vlc_mutex_lock (&p_ac3dec->fifo.data_lock);
+            vlc_mutex_lock (&p_ac3dec->p_fifo->data_lock);
 
             /* Is the input thread dying ? */
-            if (p_ac3dec->p_input->b_die)
+            if (p_ac3dec->p_fifo->b_die)
             {
-                vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
+                vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
                 return;
             }
 
@@ -390,43 +347,42 @@ void ac3_byte_stream_next (ac3_byte_stream_t * p_byte_stream)
              * pointer to the current PES packet, and we weren't able to
              * give it back to the netlist. That's why we free the PES
              * packet first. */
-            input_NetlistFreePES (p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo));
+            p_ac3dec->p_fifo->pf_delete_pes(p_ac3dec->p_fifo->p_packets_mgt,
+                    DECODER_FIFO_START(*p_ac3dec->p_fifo));
 
-            DECODER_FIFO_INCSTART (p_ac3dec->fifo);
+            DECODER_FIFO_INCSTART (*p_ac3dec->p_fifo);
 
-            while (DECODER_FIFO_ISEMPTY(p_ac3dec->fifo))
+            while (DECODER_FIFO_ISEMPTY(*p_ac3dec->p_fifo))
             {
-                vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock);
+                vlc_cond_wait(&p_ac3dec->p_fifo->data_wait, &p_ac3dec->p_fifo->data_lock);
 
-                if (p_ac3dec->p_input->b_die)
+                if (p_ac3dec->p_fifo->b_die)
                 {
-                    vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
+                    vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
                     return;
                 }
             }
 
             /* The next byte could be found in the next PES packet */
-            p_ac3dec->p_ts = DECODER_FIFO_START (p_ac3dec->fifo)->p_first_ts;
+            p_ac3dec->p_data = DECODER_FIFO_START(*p_ac3dec->p_fifo)->p_first;
 
             /* parse ac3 magic header */
-            ptr = p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+2];
+            ptr = *(p_ac3dec->p_data->p_payload_start + 2);
             ptr <<= 8;
-            ptr |= p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+3];
+            ptr |= *(p_ac3dec->p_data->p_payload_start + 3);
             p_ac3dec->sync_ptr = ptr;
-            p_ac3dec->p_ts->i_payload_start += 4;
+            p_ac3dec->p_data->p_payload_start += 4;
 
             /* We can release the fifo's data lock */
-            vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
+            vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
         }
         /* Perhaps the next TS packet of the current PES packet contains 
          * real data (ie its payload's size is greater than 0) */
         else
         {
-            p_ac3dec->p_ts = p_ac3dec->p_ts->p_next_ts;
+            p_ac3dec->p_data = p_ac3dec->p_data->p_next;
         }
-    } while (p_ac3dec->p_ts->i_payload_start == p_ac3dec->p_ts->i_payload_end);
-    p_byte_stream->p_byte =
-        p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start; 
-    p_byte_stream->p_end =
-        p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end; 
+    } while (p_ac3dec->p_data->p_payload_start == p_ac3dec->p_data->p_payload_end);
+    p_byte_stream->p_byte = p_ac3dec->p_data->p_payload_start; 
+    p_byte_stream->p_end = p_ac3dec->p_data->p_payload_end; 
 }
similarity index 86%
rename from include/ac3_decoder_thread.h
rename to src/ac3_decoder/ac3_decoder_thread.h
index 675a3ea7ac44234c1a9077aa639c7946594f765d..bbc55d45b98a64c4d5cb422c00cbf300da5db23d 100644 (file)
@@ -36,10 +36,10 @@ typedef struct ac3dec_thread_s
     /*
      * Input properties
      */
-    decoder_fifo_t      fifo;                  /* stores the PES stream data */
-    input_thread_t *    p_input;
-    ts_packet_t *       p_ts;
-    int                        sync_ptr;       /* sync ptr from ac3 magic header */
+    decoder_fifo_t *    p_fifo;                /* stores the PES stream data */
+    data_packet_t *     p_data;
+    int                sync_ptr;          /* sync ptr from ac3 magic header */
+    adec_config_t *     p_config;
 
     /*
      * Decoder properties
@@ -58,5 +58,4 @@ typedef struct ac3dec_thread_s
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
-ac3dec_thread_t *       ac3dec_CreateThread( input_thread_t * p_input );
-void                    ac3dec_DestroyThread( ac3dec_thread_t * p_ac3dec );
+vlc_thread_t            ac3dec_CreateThread( adec_config_t * p_config );
index df739a124f997465b8fde5ee5b4c6577d9db415b..4c9e1f9335cc2d9fbf0f3f6465e56ebe97fa3005 100644 (file)
 #include "debug.h"                                      /* "input_netlist.h" */
 
 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
-
-#include "input.h"                                           /* pes_packet_t */
-#include "input_netlist.h"                         /* input_NetlistFreePES() */
-#include "decoder_fifo.h"         /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
+#include "stream_control.h"
+#include "input_ext-dec.h"
 
 #include "audio_output.h"               /* aout_fifo_t (for audio_decoder.h) */
 
@@ -75,7 +74,7 @@ static void     EndThread              (adec_thread_t * p_adec);
  * This function creates a new audio decoder thread, and returns a pointer to
  * its description. On error, it returns NULL.
  *****************************************************************************/
-adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
+vlc_thread_t adec_CreateThread ( adec_config_t * p_config )
 {
     adec_thread_t *     p_adec;
 
@@ -85,7 +84,7 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
     if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
     {
         intf_ErrMsg ( "adec error: not enough memory for adec_CreateThread() to create the new thread\n" );
-        return NULL;
+        return 0;
     }
 
     /*
@@ -93,19 +92,9 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
      */
     p_adec->b_die = 0;
     p_adec->b_error = 0;
+    p_adec->p_config = p_config;
+    p_adec->p_fifo = p_config->decoder_config.p_decoder_fifo;
 
-    /*
-     * Initialize the input properties
-     */
-    /* Initialize the decoder fifo's data lock and conditional variable and set
-     * its buffer as empty */
-    vlc_mutex_init ( &p_adec->fifo.data_lock );
-    vlc_cond_init ( &p_adec->fifo.data_wait );
-    p_adec->fifo.i_start = 0;
-    p_adec->fifo.i_end = 0;
-
-    /* Initialize the bit stream structure */
-    p_adec->p_input = p_input;
 
     /*
      * Initialize the decoder properties
@@ -115,7 +104,7 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
     /*
      * Initialize the output properties
      */
-    p_adec->p_aout = p_input->p_aout;
+    p_adec->p_aout = p_config->p_aout;
     p_adec->p_aout_fifo = NULL;
 
     /* Spawn the audio decoder thread */
@@ -123,37 +112,11 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
     {
         intf_ErrMsg ("adec error: can't spawn audio decoder thread\n");
         free (p_adec);
-        return NULL;
+        return 0;
     }
 
     intf_DbgMsg ("adec debug: audio decoder thread (%p) created\n", p_adec);
-    return p_adec;
-}
-
-/*****************************************************************************
- * adec_DestroyThread: destroys an audio decoder thread
- *****************************************************************************
- * This function asks an audio decoder thread to terminate. This function has
- * not to wait until the decoder thread has really died, because the killer (ie
- * this function's caller) is the input thread, that's why we are sure that no
- * other thread will try to access to this thread's descriptor after its
- * destruction.
- *****************************************************************************/
-void adec_DestroyThread (adec_thread_t * p_adec)
-{
-    intf_DbgMsg ("adec debug: requesting termination of audio decoder thread %p\n", p_adec);
-
-    /* Ask thread to kill itself */
-    p_adec->b_die = 1;
-
-    /* Make sure the decoder thread leaves the GetByte() function */
-    vlc_mutex_lock (&(p_adec->fifo.data_lock));
-    vlc_cond_signal (&(p_adec->fifo.data_wait));
-    vlc_mutex_unlock (&(p_adec->fifo.data_lock));
-
-    /* Waiting for the decoder thread to exit */
-    /* Remove this as soon as the "status" flag is implemented */
-    vlc_thread_join (p_adec->thread_id);
+    return p_adec->thread_id;
 }
 
 /*****************************************************************************
@@ -171,24 +134,22 @@ static int InitThread (adec_thread_t * p_adec)
 
     /* Our first job is to initialize the bit stream structure with the
      * beginning of the input stream */
-    vlc_mutex_lock ( &p_adec->fifo.data_lock );
-    while ( DECODER_FIFO_ISEMPTY(p_adec->fifo) ) 
+    vlc_mutex_lock ( &p_adec->p_fifo->data_lock );
+    while ( DECODER_FIFO_ISEMPTY(*p_adec->p_fifo) ) 
     {
         if (p_adec->b_die) 
         {
-            vlc_mutex_unlock ( &p_adec->fifo.data_lock );
+            vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
             return -1;
         }
-        vlc_cond_wait ( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
+        vlc_cond_wait ( &p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock );
     }
-    p_adec->p_ts = DECODER_FIFO_START ( p_adec->fifo )->p_first_ts;
+    p_adec->p_data = DECODER_FIFO_START ( *p_adec->p_fifo )->p_first;
     byte_stream = adec_byte_stream ( &p_adec->audio_decoder );
-    byte_stream->p_byte =
-        p_adec->p_ts->buffer + p_adec->p_ts->i_payload_start;
-    byte_stream->p_end =
-        p_adec->p_ts->buffer + p_adec->p_ts->i_payload_end;
+    byte_stream->p_byte = p_adec->p_data->p_payload_start;
+    byte_stream->p_end = p_adec->p_data->p_payload_end;
     byte_stream->info = p_adec;
-    vlc_mutex_unlock ( &p_adec->fifo.data_lock );
+    vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
 
     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
     aout_fifo.i_channels = 2;
@@ -217,7 +178,8 @@ static void RunThread (adec_thread_t * p_adec)
 
     intf_DbgMsg ( "adec debug: running audio decoder thread (%p) (pid == %i)\n", p_adec, getpid() );
 
-    msleep ( INPUT_PTS_DELAY );
+    /* You really suck */
+    //msleep ( INPUT_PTS_DELAY );
 
     /* Initializing the audio decoder thread */
     if( InitThread (p_adec) )
@@ -256,11 +218,11 @@ static void RunThread (adec_thread_t * p_adec)
             sync = 1;
         }
 
-        if( DECODER_FIFO_START( p_adec->fifo)->b_has_pts )
+        if( DECODER_FIFO_START( *p_adec->p_fifo)->b_has_pts )
         {
             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
-                DECODER_FIFO_START( p_adec->fifo )->i_pts;
-            DECODER_FIFO_START(p_adec->fifo)->b_has_pts = 0;
+                DECODER_FIFO_START( *p_adec->p_fifo )->i_pts;
+            DECODER_FIFO_START(*p_adec->p_fifo)->b_has_pts = 0;
         }
         else
         {
@@ -316,25 +278,25 @@ static void ErrorThread ( adec_thread_t *p_adec )
 {
     /* We take the lock, because we are going to read/write the start/end
      * indexes of the decoder fifo */
-    vlc_mutex_lock ( &p_adec->fifo.data_lock );
+    vlc_mutex_lock ( &p_adec->p_fifo->data_lock );
 
     /* Wait until a `die' order is sent */
     while ( !p_adec->b_die ) 
     {
         /* Trash all received PES packets */
-        while ( !DECODER_FIFO_ISEMPTY(p_adec->fifo) ) 
+        while ( !DECODER_FIFO_ISEMPTY(*p_adec->p_fifo) ) 
         {
-            input_NetlistFreePES ( p_adec->p_input,
-                                   DECODER_FIFO_START(p_adec->fifo) );
-            DECODER_FIFO_INCSTART ( p_adec->fifo );
+            p_adec->p_fifo->pf_delete_pes ( p_adec->p_fifo->p_packets_mgt,
+                                   DECODER_FIFO_START(*p_adec->p_fifo) );
+            DECODER_FIFO_INCSTART ( *p_adec->p_fifo );
         }
 
         /* Waiting for the input thread to put new PES packets in the fifo */
-        vlc_cond_wait ( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
+        vlc_cond_wait ( &p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock );
     }
 
     /* We can release the lock before leaving */
-    vlc_mutex_unlock ( &p_adec->fifo.data_lock );
+    vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
 }
 
 /*****************************************************************************
@@ -373,17 +335,17 @@ void adec_byte_stream_next ( adec_byte_stream_t * p_byte_stream )
     {
         /* We were reading the last TS packet of this PES packet... It's
          * time to jump to the next PES packet */
-        if (p_adec->p_ts->p_next_ts == NULL) 
+        if (p_adec->p_data->p_next == NULL) 
         {
             /* We are going to read/write the start and end indexes of the
              * decoder fifo and to use the fifo's conditional variable,
              * that's why we need to take the lock before */
-            vlc_mutex_lock (&p_adec->fifo.data_lock);
+            vlc_mutex_lock (&p_adec->p_fifo->data_lock);
 
             /* Is the input thread dying ? */
-            if (p_adec->p_input->b_die) 
+            if (p_adec->p_fifo->b_die) 
             {
-                vlc_mutex_unlock (&(p_adec->fifo.data_lock));
+                vlc_mutex_unlock (&(p_adec->p_fifo->data_lock));
                 return;
             }
 
@@ -392,40 +354,39 @@ void adec_byte_stream_next ( adec_byte_stream_t * p_byte_stream )
              * pointer to the current PES packet, and we weren't able to
              * give it back to the netlist. That's why we free the PES
              * packet first. */
-            input_NetlistFreePES (p_adec->p_input, DECODER_FIFO_START(p_adec->fifo));
-            DECODER_FIFO_INCSTART (p_adec->fifo);
+            p_adec->p_fifo->pf_delete_pes (p_adec->p_fifo->p_packets_mgt,
+                    DECODER_FIFO_START(*p_adec->p_fifo));
+            DECODER_FIFO_INCSTART (*p_adec->p_fifo);
 
-            while (DECODER_FIFO_ISEMPTY(p_adec->fifo)) 
+            while (DECODER_FIFO_ISEMPTY(*p_adec->p_fifo)) 
             {
-                vlc_cond_wait (&p_adec->fifo.data_wait, &p_adec->fifo.data_lock);
-                if (p_adec->p_input->b_die) 
+                vlc_cond_wait (&p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock);
+                if (p_adec->p_fifo->b_die) 
                 {
-                    vlc_mutex_unlock (&(p_adec->fifo.data_lock));
+                    vlc_mutex_unlock (&(p_adec->p_fifo->data_lock));
                     return;
                 }
             }
 
             /* The next byte could be found in the next PES packet */
-            p_adec->p_ts = DECODER_FIFO_START (p_adec->fifo)->p_first_ts;
-            if (DECODER_FIFO_START (p_adec->fifo)->b_data_alignment)
+            p_adec->p_data = DECODER_FIFO_START (*p_adec->p_fifo)->p_first;
+            if (DECODER_FIFO_START (*p_adec->p_fifo)->b_data_alignment)
             {
                 p_adec->align = 1;
             }
 
             /* We can release the fifo's data lock */
-            vlc_mutex_unlock (&p_adec->fifo.data_lock);
+            vlc_mutex_unlock (&p_adec->p_fifo->data_lock);
         }
         /* Perhaps the next TS packet of the current PES packet contains
          * real data (ie its payload's size is greater than 0) */
         else 
         {
-            p_adec->p_ts = p_adec->p_ts->p_next_ts;
+            p_adec->p_data = p_adec->p_data->p_next;
         }
-    } while (p_adec->p_ts->i_payload_start == p_adec->p_ts->i_payload_end);
+    } while (p_adec->p_data->p_payload_start == p_adec->p_data->p_payload_end);
 
     /* We've found a TS packet which contains interesting data... */
-    p_byte_stream->p_byte =
-        p_adec->p_ts->buffer + p_adec->p_ts->i_payload_start;
-    p_byte_stream->p_end =
-        p_adec->p_ts->buffer + p_adec->p_ts->i_payload_end;
+    p_byte_stream->p_byte = p_adec->p_data->p_payload_start;
+    p_byte_stream->p_end = p_adec->p_data->p_payload_end;
 }
similarity index 87%
rename from include/audio_decoder_thread.h
rename to src/audio_decoder/audio_decoder_thread.h
index 52d131323eac17c743c8b2b55ffe2b9ca52ba6f8..2d3b75b2c14c450dea2cbedf514ee5efc486139f 100644 (file)
@@ -36,10 +36,11 @@ typedef struct adec_thread_s
     /*
      * Input properties
      */
-    decoder_fifo_t      fifo;                  /* stores the PES stream data */
-    input_thread_t *    p_input;
-    ts_packet_t *       p_ts;
-    int                        align;
+    decoder_fifo_t *    p_fifo;                /* stores the PES stream data */
+    data_packet_t *     p_data;
+    int                 align;
+    adec_config_t *     p_config;
+
 
     /*
      * Decoder properties
@@ -57,5 +58,4 @@ typedef struct adec_thread_s
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
-adec_thread_t * adec_CreateThread       ( input_thread_t * p_input /* !! , aout_thread_t * p_aout !! */ );
-void            adec_DestroyThread      ( adec_thread_t * p_adec );
+vlc_thread_t adec_CreateThread       ( adec_config_t * p_config );
index 422058636e3d66870a875b5a0742e4c237a1350e..8c62b4872a7b349dc92b3799d54ee8f118ae390e 100644 (file)
@@ -5,8 +5,7 @@
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
  *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *          Benoît Steiner <benny@via.ecp.fr>
+ * 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
  *****************************************************************************/
 #include "defs.h"
 
-#include <errno.h>                                                  /* errno */
-#include <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
-#include <string.h>                                            /* strerror() */
-
-#include <stdlib.h>                                                /* free() */
-#include <netinet/in.h>                                           /* ntohs() */
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
 
 #include "config.h"
 #include "common.h"
 #include "threads.h"
 #include "mtime.h"
-#include "intf_msg.h"
-#include "plugins.h"
-#include "debug.h"
-
-#include "input.h"
-#include "input_psi.h"
-#include "input_pcr.h"
-#include "input_netlist.h"
-#include "decoder_fifo.h"
-#include "input_file.h"
-#include "input_network.h"
-
-#include "audio_output.h"                                   /* aout_thread_t */
-
-#include "audio_decoder.h"        /* audiodec_t (for audio_decoder_thread.h) */
-#include "audio_decoder_thread.h"                           /* adec_thread_t */
-
-#include "ac3_decoder.h"              /* ac3dec_t (for ac3_decoder_thread.h) */
-#include "ac3_decoder_thread.h"                           /* ac3dec_thread_t */
 
-#include "lpcm_decoder.h"
-#include "lpcm_decoder_thread.h"
-
-#include "video.h"                          /* picture_t (for video_output.h) */
-#include "video_output.h"                                   /* vout_thread_t */
-
-#include "vdec_idct.h"                     /* dctelem_t (for video_parser.h) */
-#include "vdec_motion.h"                  /* f_motion_t (for video_parser.h) */
-#include "vpar_blocks.h"                /* macroblock_t (for video_parser.h) */
-#include "vpar_headers.h"                 /* sequence_t (for video_parser.h) */
-#include "vpar_synchro.h"            /* video_synchro_t (for video_parser.h) */
-#include "video_parser.h"                                   /* vpar_thread_t */
+#include "intf_msg.h"
 
-#include "spu_decoder.h"                                  /* spudec_thread_t */
+#include "stream_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
 
-#include "main.h"
+#include "input.h"
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
 static void RunThread   ( input_thread_t *p_input );
+static void InitThread  ( input_thread_t *p_input );
 static void ErrorThread ( input_thread_t *p_input );
 static void EndThread   ( input_thread_t *p_input );
-
-static __inline__ int   input_ReadPacket( input_thread_t *p_input );
-static __inline__ void  input_SortPacket( input_thread_t *p_input,
-                                          ts_packet_t *ts_packet );
-static __inline__ void  input_DemuxTS( input_thread_t *p_input,
-                                       ts_packet_t *ts_packet,
-                                       es_descriptor_t *es_descriptor );
-static __inline__ void  input_DemuxPES( input_thread_t *p_input,
-                                        ts_packet_t *ts_packet,
-                                        es_descriptor_t *p_es_descriptor,
-                                        boolean_t b_unit_start,
-                                        boolean_t b_packet_lost );
-static __inline__ void  input_ParsePES( input_thread_t *p_input,
-                                        es_descriptor_t *p_es_descriptor );
-static __inline__ void  input_DemuxPSI( input_thread_t *p_input,
-                                        ts_packet_t *ts_packet,
-                                        es_descriptor_t *p_es_descriptor,
-                                        boolean_t b_unit_start,
-                                        boolean_t b_packet_lost );
+static void NetworkOpen ( input_thread_t *p_input );
+static void FileOpen    ( input_thread_t *p_input );
 
 /*****************************************************************************
  * input_CreateThread: creates a new input thread
@@ -111,143 +66,68 @@ static __inline__ void  input_DemuxPSI( input_thread_t *p_input,
  * If pi_status is NULL, then the function will block until the thread is ready.
  * If not, it will be updated using one of the THREAD_* constants.
  *****************************************************************************/
-input_thread_t *input_CreateThread ( int i_method, void *p_source, int i_port,
-                                     int i_vlan, p_vout_thread_t p_vout,
-                                     p_aout_thread_t p_aout, int *pi_status )
+input_thread_t *input_CreateThread ( input_config_t * p_config, int *pi_status )
 {
     input_thread_t *    p_input;                        /* thread descriptor */
     int                 i_status;                           /* thread status */
-    int                 i_index;          /* index for tables initialization */
+    int                 i;
 
     /* Allocate descriptor */
     intf_DbgMsg("\n");
     p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
     if( p_input == NULL )
     {
-        intf_ErrMsg("error: %s\n", strerror(ENOMEM));
+        intf_ErrMsg("error: %s\n", strerror(errno));
+        free( p_config );
         return( NULL );
     }
 
     /* Initialize thread properties */
     p_input->b_die              = 0;
     p_input->b_error            = 0;
+    /* I have never understood that stuff --Meuuh */
     p_input->pi_status          = (pi_status != NULL) ? pi_status : &i_status;
     *p_input->pi_status         = THREAD_CREATE;
-
-    /* Initialize input method description */
-    p_input->i_method           = i_method;
-    p_input->p_source           = p_source;
-    p_input->i_port             = i_port;
-    p_input->i_vlan             = i_vlan;
-    switch( i_method )
-    {
-    case INPUT_METHOD_TS_FILE:                               /* file methods */
-        p_input->p_Open =   input_FileOpen;
-        p_input->p_Read =   input_FileRead;
-        p_input->p_Close =  input_FileClose;
-        break;
-    case INPUT_METHOD_TS_VLAN_BCAST:                  /* vlan network method */
-        if( !p_main->b_vlans )
-        {
-            intf_ErrMsg("error: vlans are not activated\n");
-            free( p_input );
-            return( NULL );
-        }
-        /* ... pass through */
-    case INPUT_METHOD_TS_UCAST:                           /* network methods */
-    case INPUT_METHOD_TS_MCAST:
-    case INPUT_METHOD_TS_BCAST:
-        p_input->p_Open =   input_NetworkOpen;
-        p_input->p_Read =   input_NetworkRead;
-        p_input->p_Close =  input_NetworkClose;
-        break;
-    default:
-        intf_ErrMsg("error: unknow input method\n");
-        free( p_input );
-        return( NULL );
-        break;
-    }
+    p_input->p_config = p_config;
 
     /* Initialize stream description */
-    for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
-    {
-        p_input->p_es[i_index].i_id = EMPTY_PID;
-        p_input->pp_selected_es[i_index] = NULL;
-    }
-
-    /* Initialize default settings for spawned decoders */
-    p_input->p_aout                     = p_aout;
-    p_input->p_vout                     = p_vout;
-
-#ifdef STATS
-    /* Initialize statistics */
-    p_input->c_loops                    = 0;
-    p_input->c_bytes                    = 0;
-    p_input->c_payload_bytes            = 0;
-    p_input->c_packets_read             = 0;
-    p_input->c_packets_trashed          = 0;
-#endif
-
-    /* Initialize PSI and PCR decoders */
-    if( input_PsiInit( p_input ) )
-    {
-        free( p_input );
-        return( NULL );
-    }
-
-    if( input_PcrInit( p_input ) )
+    for( i = 0; i < INPUT_MAX_SELECTED_ES; i++ )
     {
-        input_PsiEnd( p_input );
-        free( p_input );
-        return( NULL );
+        p_input->pp_selected_es[i] = NULL;
     }
-
-    /* Initialize netlists */
-    if( input_NetlistInit( p_input ) )
+    for( i= 0; i < INPUT_MAX_ES; i++ )
     {
-        input_PsiEnd( p_input );
-        input_PcrEnd( p_input );
-        free( p_input );
-        return( NULL );
+        p_input->p_es[i].i_id = EMPTY_ID;
     }
+    p_input->stream.i_pgrm_number = 0;
 
-    intf_DbgMsg("configuration: method=%d, source=%s, port=%d, vlan=%d\n",
-                i_method, p_source, i_port, i_vlan );
-
-    /* Let the appropriate method open the socket. */
-    if( p_input->p_Open( p_input ) )
-    {
-        input_NetlistEnd( p_input );
-        input_PsiEnd( p_input );
-        input_PcrEnd( p_input );
-        free( p_input );
-        return( NULL );
-    }
+    /* Initialize stream control properties. */
+    p_input->stream.control.i_status = PLAYING_S;
+    p_input->stream.control.i_rate = DEFAULT_RATE;
+    p_input->stream.control.i_ref_sysdate = 0;
+    p_input->stream.control.i_ref_clock = 0;
+    p_input->stream.control.b_mute = 0;
+    p_input->stream.control.b_bw = 0;
 
     /* Create thread and set locks. */
-    vlc_mutex_init( &p_input->netlist.lock );
-    vlc_mutex_init( &p_input->programs_lock );
-    vlc_mutex_init( &p_input->es_lock );
-    if( vlc_thread_create(&p_input->thread_id, "input", (void *) RunThread, (void *) p_input) )
+    vlc_mutex_init( &p_input->stream.stream_lock );
+    vlc_mutex_init( &p_input->stream.control.control_lock );
+    if( vlc_thread_create( &p_input->thread_id, "input", (void *) RunThread,
+                           (void *) p_input ) )
     {
         intf_ErrMsg("error: %s\n", strerror(errno) );
-        p_input->p_Close( p_input );
-        input_NetlistEnd( p_input );;
-        input_PsiEnd( p_input );
-        input_PcrEnd( p_input );
         free( p_input );
+        free( p_config );
         return( NULL );
     }
 
-    intf_Msg("Input initialized\n");
-
     /* If status is NULL, wait until the thread is created */
     if( pi_status == NULL )
     {
         do
         {
             msleep( THREAD_SLEEP );
-        }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
+        } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
                 && (i_status != THREAD_FATAL) );
         if( i_status != THREAD_READY )
         {
@@ -279,1181 +159,228 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
         do
         {
             msleep( THREAD_SLEEP );
-        }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
-                && (i_status != THREAD_FATAL) );
+        } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
+                  && (i_status != THREAD_FATAL) );
     }
 }
 
-#if 0
-/*****************************************************************************
- * input_OpenAudioStream: open an audio stream
- *****************************************************************************
- * This function spawns an audio decoder and plugs it on the audio output
- * thread.
- *****************************************************************************/
-int input_OpenAudioStream( input_thread_t *p_input, int i_id )
-{
-    /* XXX?? */
-}
-
 /*****************************************************************************
- * input_CloseAudioStream: close an audio stream
+ * RunThread: main thread loop
  *****************************************************************************
- * This function destroys an audio decoder.
+ * Thread in charge of processing the network packets and demultiplexing.
  *****************************************************************************/
-void input_CloseAudioStream( input_thread_t *p_input, int i_id )
+static void RunThread( input_thread_t *p_input )
 {
-    /* XXX?? */
-}
+    data_packet_t *      pp_packets[INPUT_READ_ONCE];
 
-/*****************************************************************************
- * input_OpenVideoStream: open a video stream
- *****************************************************************************
- * This function spawns a video decoder and plugs it on a video output thread.
- *****************************************************************************/
-int input_OpenVideoStream( input_thread_t *p_input,
-                           struct vout_thread_s *p_vout, struct video_cfg_s * p_cfg )
-{
-    /* XXX?? */
-}
+    InitThread( p_input );
 
-/*****************************************************************************
- * input_CloseVideoStream: close a video stream
- *****************************************************************************
- * This function destroys an video decoder.
- *****************************************************************************/
-void input_CloseVideoStream( input_thread_t *p_input, int i_id )
-{
-    /* XXX?? */
-}
+    while( !p_input->b_die && !p_input->b_error )
+    {
+#ifdef STATS
+        p_input->c_loops++;
 #endif
 
-/* following functions are local */
-
-/*****************************************************************************
- * InitThread: initialize input thread
- *****************************************************************************
- * This function is called from RunThread and performs the second step of the
- * initialization. It returns 0 on success. Note that the thread's flag are not
- * modified inside this function.
- *****************************************************************************/
-static int InitThread( input_thread_t *p_input )
-{
-    /* Mark thread as running and return */
-    intf_DbgMsg("\n");
-    *p_input->pi_status =        THREAD_READY;
-    intf_DbgMsg("thread ready\n");
-    return( 0 );
-}
-
-/*****************************************************************************
- * input_DemuxPSI:
- *****************************************************************************
- * Notice that current ES state has been locked by input_SortPacket.
- * (No more true, changed by benny - FIXME: See if it's ok, and definitely
- * change the code ?? )
- *****************************************************************************/
-static __inline__ void input_DemuxPSI( input_thread_t *p_input,
-                                       ts_packet_t *p_ts_packet,
-                                       es_descriptor_t *p_es_descriptor,
-                                       boolean_t b_unit_start,
-                                       boolean_t b_packet_lost )
-{
-    int i_data_offset;    /* Offset of the interesting data in the TS packet */
-    u16 i_data_length;                               /* Length of those data */
-  //boolean_t b_first_section;         /* another section in the TS packet ? */
-
-    ASSERT(p_input);
-    ASSERT(p_ts_packet);
-    ASSERT(p_es_descriptor);
-
-#define p_psi (p_es_descriptor->p_psi_section)
-
-    //intf_DbgMsg( "input debug: PSI demultiplexing %p (%p)\n", p_ts_packet, p_input);
-
-    //intf_DbgMsg( "Packet: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x (unit start: %d)\n", p_ts_packet->buffer[p_ts_packet->i_payload_start], p_ts_packet->buffer[p_ts_packet->i_payload_start+1], p_ts_packet->buffer[p_ts_packet->i_payload_start+2], p_ts_packet->buffer[p_ts_packet->i_payload_start+3], p_ts_packet->buffer[p_ts_packet->i_payload_start+4], p_ts_packet->buffer[p_ts_packet->i_payload_start+5], p_ts_packet->buffer[p_ts_packet->i_payload_start+6], p_ts_packet->buffer[p_ts_packet->i_payload_start+7], p_ts_packet->buffer[p_ts_packet->i_payload_start+8], p_ts_packet->buffer[p_ts_packet->i_payload_start+9], p_ts_packet->buffer[p_ts_packet->i_payload_start+10], p_ts_packet->buffer[p_ts_packet->i_payload_start+11], p_ts_packet->buffer[p_ts_packet->i_payload_start+12], p_ts_packet->buffer[p_ts_packet->i_payload_start+13], p_ts_packet->buffer[p_ts_packet->i_payload_start+14], p_ts_packet->buffer[p_ts_packet->i_payload_start+15], p_ts_packet->buffer[p_ts_packet->i_payload_start+16], p_ts_packet->buffer[p_ts_packet->i_payload_start+17], p_ts_packet->buffer[p_ts_packet->i_payload_start+18], p_ts_packet->buffer[p_ts_packet->i_payload_start+19], p_ts_packet->buffer[p_ts_packet->i_payload_start+20], b_unit_start);
-
-
-    /* Try to find the beginning of the payload in the packet to initialise
-     * the do-while loop that follows -> Compute the i_data_offset variable:
-     * by default, the value is set so that we won't enter in the while loop.
-     * It will be set to a correct value if the data are not corrupted */
-    i_data_offset = TS_PACKET_SIZE;
-
-    /* Has the reassembly of a section already begun in a previous packet ? */
-    if( p_psi->b_running_section )
-    {
-        /* Was data lost since the last TS packet ? */
-        if( b_packet_lost )
-        {
-            /* Discard the packet and wait for the begining of a new one
-             * to resynch */
-            p_psi->b_running_section = 0;
-            p_psi->i_current_position = 0;
-            intf_DbgMsg( "PSI section(s) discarded due to packet loss\n" );
-        }
-        else
-        {
-            /* The data that complete a previously began section are always at
-             * the beginning of the TS payload... */
-            i_data_offset = p_ts_packet->i_payload_start;
-            /* ...Unless there is a pointer field, that we have to bypass */
-            if( b_unit_start )
-                i_data_offset++;
-            //intf_DbgMsg( "New part of the section received at offset %d\n", i_data_offset );
-        }
-    }
-    /* We are looking for the beginning of a new section */
-    else
-    {
-        if( b_unit_start )
-        {
-            /* Get the offset at which the data for that section can be found
-             * The offset is stored in the pointer_field since we are
-             * interested in the first section of the TS packet. Note that
-             * the +1 is to bypass the pointer field */
-            i_data_offset = p_ts_packet->i_payload_start +
-                            p_ts_packet->buffer[p_ts_packet->i_payload_start] + 1;
-            //intf_DbgMsg( "New section beginning at offset %d in TS packet\n", i_data_offset );
-        }
-        else
+        vlc_mutex_lock( &p_input->stream.control.control_lock );
+        if( p_input->stream.control.i_status == BACKWARD_S
+             && p_input->p_plugin->pf_rewind != NULL )
         {
-            /* This may either mean that the TS is bad or that the packet
-             * contains the end of a section that had been discarded in a
-             * previous loop: trash the TS packet since we cannot do
-             * anything with those data: */
-            p_psi->b_running_section = 0;
-            p_psi->i_current_position = 0;
-            intf_DbgMsg( "PSI packet discarded due to lack of synchronisation\n" );
+            p_input->p_plugin->pf_rewind( p_input );
+            /* FIXME: probably don't do it every loop, but when ? */
         }
-    }
-
-    /* The section we will deal with during the first iteration of the
-     * following loop is the first one contained in the TS packet */
-    //    b_first_section = 1;
+        vlc_mutex_unlock( &p_input->stream.control.control_lock );
 
-    /* Reassemble the pieces of sections contained in the TS packet and
-     * decode the sections that could have been completed.
-     * Stop when we reach the end of the packet or stuffing bytes */
-    while( i_data_offset < TS_PACKET_SIZE && p_ts_packet->buffer[i_data_offset] != 0xFF )
-    {
-        /* If the current section is a new one, reinit the data fields of
-         * the p_psi struct to start its decoding */
-        if( !p_psi->b_running_section )
+        p_input->p_plugin->pf_read( p_input, pp_packets );
+        if( !p_input->b_error )
         {
-            /* Read the length of the new section */
-            p_psi->i_length = (U16_AT(&p_ts_packet->buffer[i_data_offset+1]) & 0xFFF) + 3;
-            //intf_DbgMsg( "Section length %d\n", p_psi->i_length );
-            if( p_psi->i_length > PSI_SECTION_SIZE )
+            int     i;
+
+            for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
             {
-                /* The TS packet is corrupted, stop here to avoid possible
-                 * a seg fault */
-                intf_DbgMsg( "PSI Section size is too big, aborting its reception\n" );
-                break;
+                p_input->p_plugin->pf_demux( p_input, pp_packets[i] );
             }
-
-            /* Init the reassembly of that section */
-            p_psi->b_running_section = 1;
-            p_psi->i_current_position = 0;
-        }
-
-      /* Compute the length of data related to the section in this TS packet */
-        if( p_psi->i_length - p_psi->i_current_position > TS_PACKET_SIZE - i_data_offset)
-            i_data_length = TS_PACKET_SIZE - i_data_offset;
-        else
-          i_data_length = p_psi->i_length - p_psi->i_current_position;
-
-        /* Copy those data in the section buffer */
-        memcpy( &p_psi->buffer[p_psi->i_current_position], &p_ts_packet->buffer[i_data_offset],
-                i_data_length );
-
-        /* Interesting data are now after the ones we copied, since no gap is
-         * allowed between 2 sections in a TS packets */
-        i_data_offset += i_data_length;
-
-        /* Decode the packet if it is now complete */
-        if (p_psi->i_length == p_psi->i_current_position + i_data_length)
-        {
-            /* Packet is complete, decode it */
-            //intf_DbgMsg( "SECTION COMPLETE: starting decoding of its data\n" );
-            input_PsiDecode( p_input, p_psi );
-
-            /* Prepare the buffer to receive a new section */
-            p_psi->i_current_position = 0;
-            p_psi->b_running_section = 0;
-
-            /* The new section won't be the first anymore */
-            //b_first_section = 0;
-        }
-        else
-        {
-            /* Prepare the buffer to receive the next part of the section */
-          p_psi->i_current_position += i_data_length;
-          //intf_DbgMsg( "Section not complete, waiting for the end\n" );
         }
-
-        //intf_DbgMsg( "Must loop ? Next data offset: %d, stuffing: %d\n",
-        //             i_data_offset, p_ts_packet->buffer[i_data_offset] );
     }
 
-    /* Relase the TS packet, we don't need it anymore */
-    input_NetlistFreeTS( p_input, p_ts_packet );
+    if( p_input->b_error )
+    {
+        ErrorThread( p_input );
+    }
 
-#undef p_psi
+    EndThread( p_input );
+    intf_DbgMsg("Thread end");
 }
 
 /*****************************************************************************
- * input_ParsePES
- *****************************************************************************
- * Parse a finished PES packet and analyze its header.
+ * InitThread: init the input thread
  *****************************************************************************/
-static __inline__ void input_ParsePES( input_thread_t *p_input,
-                                       es_descriptor_t *p_es_descriptor )
+input_capabilities_t * PSKludge( void );
+static void InitThread( input_thread_t * p_input )
 {
-    decoder_fifo_t *            p_fifo;
-    u8                          i_pes_header_size;
-    ts_packet_t *               p_ts;
-    int                         i_ts_payload_size;
-
-
-#define p_pes (p_es_descriptor->p_pes_packet)
-
-    //intf_DbgMsg("End of PES packet %p\n", p_pes);
-
-    /* First read the 6 header bytes common to all PES packets:
-       use them to test the PES validity */
-    if( (p_pes->p_pes_header[0] || p_pes->p_pes_header[1] ||
-        (p_pes->p_pes_header[2] != 1)) ||
-                                 /* packet_start_code_prefix != 0x000001 */
-        ((p_pes->i_pes_real_size) &&
-         (p_pes->i_pes_real_size != p_pes->i_pes_size)) )
-               /* PES_packet_length is set and != total received payload */
-    {
-      /* Trash the packet and set p_pes to NULL to be sure the next PES
-         packet will have its b_data_lost flag set */
-      intf_DbgMsg("Corrupted PES packet (size doesn't match) : trashed\n");
-      input_NetlistFreePES( p_input, p_pes );
-      p_pes = NULL;
-      /* Stats XXX?? */
-    }
-    else
-    {
-        /* The PES packet is valid. Check its type to test if it may
-           carry additional informations in a header extension */
-        p_pes->i_stream_id =  p_pes->p_pes_header[3];
-
-        switch( p_pes->i_stream_id )
-        {
-        case 0xBE:  /* Padding */
-        case 0xBC:  /* Program stream map */
-        case 0xBF:  /* Private stream 2 */
-        case 0xB0:  /* ECM */
-        case 0xB1:  /* EMM */
-        case 0xFF:  /* Program stream directory */
-        case 0xF2:  /* DSMCC stream */
-        case 0xF8:  /* ITU-T H.222.1 type E stream */
-            /* The payload begins immediatly after the 6 bytes header, so
-               we have finished with the parsing */
-            i_pes_header_size = 6;
-            break;
-
-        default:
-            switch( p_pes->p_pes_header[8] & 0xc0 )
-            {
-              case 0x80: /* MPEG2: 10xx xxxx */
-              case 0x00: /* FIXME: This shouldn't be allowed !! */
-                /* The PES header contains at least 3 more bytes: parse them */
-                p_pes->b_data_alignment = p_pes->p_pes_header[6] & 0x04;
-                p_pes->b_has_pts = p_pes->p_pes_header[7] & 0x80;
-                i_pes_header_size = p_pes->p_pes_header[8] + 9;
-
-                /* Now parse the optional header extensions (in the limit of
-                   the 14 bytes */
-                if( p_pes->b_has_pts )
-                {
-                    pcr_descriptor_t * p_pcr;
-
-                    p_pcr = p_input->p_pcr;
-
-                    p_pes->i_pts =
-                        ( ((mtime_t)(p_pes->p_pes_header[9] & 0x0E) << 29) |
-                          (((mtime_t)U16_AT(p_pes->p_pes_header + 10) << 14) - (1 << 14)) |
-                          ((mtime_t)U16_AT(p_pes->p_pes_header + 12) >> 1) ) * 300;
-                    p_pes->i_pts /= 27;
-
-                    if( p_pcr->i_synchro_state )
-                    {
-                        switch( p_pcr->i_synchro_state )
-                        {
-                            case SYNCHRO_NOT_STARTED:
-                                p_pes->b_has_pts = 0;
-                                break;
-
-                            case SYNCHRO_START:
-                                p_pes->i_pts += p_pcr->delta_pcr;
-                                p_pcr->delta_absolute = mdate() - p_pes->i_pts + INPUT_PTS_DELAY;
-                                p_pes->i_pts += p_pcr->delta_absolute;
-                                p_pcr->i_synchro_state = 0;
-                                break;
-
-                            case SYNCHRO_REINIT: /* We skip a PES */
-                                p_pes->b_has_pts = 0;
-                                p_pcr->i_synchro_state = SYNCHRO_START;
-                                break;
-                        }
-                    }
-                    else
-                    {
-                        p_pes->i_pts += p_pcr->delta_pcr + p_pcr->delta_absolute;
-                    }
-                }
-                break;
-
-            default: /* MPEG1 or some strange thing */
-                /* since this isn't supported yet, we certainly gonna crash */
-                intf_ErrMsg( "FIXME: unknown PES type %.2x\n",
-                             p_pes->p_pes_header[8] );
-                i_pes_header_size = 6;
-                break;
-
-            }
-            break;
-        }
-
-        /* Now we've parsed the header, we just have to indicate in some
-         * specific TS packets where the PES payload begins (renumber
-         * i_payload_start), so that the decoders can find the beginning
-         * of their data right out of the box. */
-        p_ts = p_pes->p_first_ts;
-        i_ts_payload_size = p_ts->i_payload_end - p_ts->i_payload_start;
-        while( i_pes_header_size > i_ts_payload_size )
-        {
-            /* These packets are entirely filled by the PES header. */
-            i_pes_header_size -= i_ts_payload_size;
-            p_ts->i_payload_start = p_ts->i_payload_end;
-            /* Go to the next TS packet: here we won't have to test it is
-             * not NULL because we trash the PES packets when packet lost
-             * occurs */
-            p_ts = p_ts->p_next_ts;
-            i_ts_payload_size = p_ts->i_payload_end - p_ts->i_payload_start;
-        }
-        /* This last packet is partly header, partly payload. */
-        p_ts->i_payload_start += i_pes_header_size;
-
-
-        /* Now we can eventually put the PES packet in the decoder's
-         * PES fifo */
-        switch( p_es_descriptor->i_type )
-        {
-            case MPEG1_VIDEO_ES:
-            case MPEG2_VIDEO_ES:
-                p_fifo = &(((vpar_thread_t*)(p_es_descriptor->p_dec))->fifo);
-                break;
-
-            case MPEG1_AUDIO_ES:
-            case MPEG2_AUDIO_ES:
-                p_fifo = &(((adec_thread_t*)(p_es_descriptor->p_dec))->fifo);
-                break;
-
-            case AC3_AUDIO_ES:
-                p_fifo = &(((ac3dec_thread_t *)(p_es_descriptor->p_dec))->fifo);
-                break;
-
-           case LPCM_AUDIO_ES:
-                p_fifo = &(((lpcmdec_thread_t *)(p_es_descriptor->p_dec))->fifo);
-                break;
-
-            case DVD_SPU_ES:
-                /* we skip the first byte at the beginning of the
-                 * subpicture payload, it only contains the SPU ID. */
-                p_ts->i_payload_start++;
-                p_fifo = &(((spudec_thread_t *)(p_es_descriptor->p_dec))->fifo);
-                break;
-
-            default:
-                /* This should never happen */
-                intf_DbgMsg("Unknown stream type (%d, %d): PES trashed\n",
-                    p_es_descriptor->i_id, p_es_descriptor->i_type);
-                p_fifo = NULL;
-                break;
-        }
+    /* Initialize default settings for spawned decoders */
+    p_input->p_default_aout     = p_input->p_config->p_default_aout;
+    p_input->p_default_vout     = p_input->p_config->p_default_vout;
 
-        if( p_fifo != NULL )
-        {
-            vlc_mutex_lock( &p_fifo->data_lock );
-            if( DECODER_FIFO_ISFULL( *p_fifo ) )
-            {
-                /* The FIFO is full !!! This should not happen. */
 #ifdef STATS
-                p_input->c_packets_trashed += p_pes->i_ts_packets;
-                p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;
+    /* Initialize statistics */
+    p_input->c_loops                    = 0;
+    p_input->c_bytes                    = 0;
+    p_input->c_payload_bytes            = 0;
+    p_input->c_packets_read             = 0;
+    p_input->c_packets_trashed          = 0;
 #endif
-                input_NetlistFreePES( p_input, p_pes );
-                intf_DbgMsg("PES trashed - fifo full ! (%d, %d)\n",
-                           p_es_descriptor->i_id, p_es_descriptor->i_type);
-            }
-        else
-            {
-                //intf_DbgMsg("Putting %p into fifo %p/%d\n",
-                //            p_pes, p_fifo, p_fifo->i_end);
-                p_fifo->buffer[p_fifo->i_end] = p_pes;
-                DECODER_FIFO_INCEND( *p_fifo );
 
-                /* Warn the decoder that it's got work to do. */
-                vlc_cond_signal( &p_fifo->data_wait );
-            }
-            vlc_mutex_unlock( &p_fifo->data_lock );
-        }
-        else
+    /* Use the appropriate input method */
+    switch( p_input->p_config->i_method )
+    {
+    case INPUT_METHOD_FILE:                                  /* file methods */
+        FileOpen( p_input );
+        break;
+    case INPUT_METHOD_VLAN_BCAST:                     /* vlan network method */
+/*        if( !p_main->b_vlans )
         {
-            intf_DbgMsg("No fifo to receive PES %p: trash\n", p_pes);
-#ifdef STATS
-            p_input->c_packets_trashed += p_pes->i_ts_packets;
-            p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;
+            intf_ErrMsg("error: vlans are not activated\n");
+            free( p_input );
+            return( NULL );
+        } */ /* la-lala */
+        /* ... pass through */
+    case INPUT_METHOD_UCAST:                              /* network methods */
+    case INPUT_METHOD_MCAST:
+    case INPUT_METHOD_BCAST:
+        NetworkOpen( p_input );
+        break;
+#ifdef DEBUG
+    default:
+        intf_ErrMsg("Unknow input method");
+        free( p_input->p_config );
+        p_input->b_error = 1;
+        break;
 #endif
-            input_NetlistFreePES( p_input, p_pes );
-        }
     }
-#undef p_pes
+
+    free( p_input->p_config );
+
+    /* Probe plugin (FIXME: load plugins before & write this) */
+    p_input->p_plugin = PSKludge();
+    p_input->p_plugin->pf_init( p_input );
+
+    *p_input->pi_status = THREAD_READY;
 }
 
 /*****************************************************************************
- * input_DemuxPES:
+ * ErrorThread: RunThread() error loop
  *****************************************************************************
- * Gather a PES packet.
+ * This function is called when an error occured during thread main's loop.
  *****************************************************************************/
-static __inline__ void input_DemuxPES( input_thread_t *p_input,
-                                       ts_packet_t *p_ts_packet,
-                                       es_descriptor_t *p_es_descriptor,
-                                       boolean_t b_unit_start,
-                                       boolean_t b_packet_lost )
+static void ErrorThread( input_thread_t *p_input )
 {
-    int                         i_dummy;
-    pes_packet_t*               p_last_pes;
-    ts_packet_t *               p_ts;
-    int                         i_ts_payload_size;
-
-
-#define p_pes (p_es_descriptor->p_pes_packet)
-
-    ASSERT(p_input);
-    ASSERT(p_ts_packet);
-    ASSERT(p_es_descriptor);
-
-    //intf_DbgMsg("PES-demultiplexing %p (%p)\n", p_ts_packet, p_pes);
-
-    /* If we lost data, discard the PES packet we are trying to reassemble
-       if any and wait for the beginning of a new one in order to synchronise
-       again */
-    if( b_packet_lost && p_pes != NULL )
-    {
-        intf_DbgMsg("PES %p trashed because of packet lost\n", p_pes);
-        input_NetlistFreePES( p_input, p_pes );
-        p_pes = NULL;
-    }
-
-    /* If the TS packet contains the begining of a new PES packet, and if we
-       were reassembling a PES packet, then the PES should be complete now,
-       so parse its header and give it to the decoders */
-    if( b_unit_start && p_pes != NULL )
-    {
-        /* Parse the header. The header has a variable length, but in order
-           to improve the algorithm, we will read the 14 bytes we may be
-           interested in */
-
-        /* If this part of the header did not fit in the current TS packet,
-           copy the part of the header we are interested in to the
-           p_pes_header_save buffer. The buffer is dynamicly allocated if
-           needed so it's time expensive but this situation almost never
-           occurs. */
-        p_ts = p_pes->p_first_ts;
-        i_ts_payload_size = p_ts->i_payload_end - p_ts->i_payload_start;
-
-        if(i_ts_payload_size < PES_HEADER_SIZE)
-        {
-            intf_WarnMsg(3, "Code never tested encountered, WARNING ! (benny)\n");
-            if( !p_pes->p_pes_header_save )
-            {
-                p_pes->p_pes_header_save = malloc(PES_HEADER_SIZE);
-            }
-
-            i_dummy = 0;
-            do
-            {
-                memcpy( p_pes->p_pes_header_save + i_dummy,
-                        &p_ts->buffer[p_ts->i_payload_start],
-                        i_ts_payload_size);
-                i_dummy += i_ts_payload_size;
-
-                p_ts = p_ts->p_next_ts;
-                if(!p_ts)
-                {
-                  /* The payload of the PES packet is shorter than the 14 bytes
-                     we would read. This means that high packet lost occured
-                     so the PES won't be useful for any decoder. Moreover,
-                     this should never happen so we can trash the packet and
-                     exit roughly without regrets */
-                  intf_DbgMsg("PES packet too short: trashed\n");
-                  input_NetlistFreePES( p_input, p_pes );
-                  p_pes = NULL;
-                  /* XXX: Stats */
-                  return;
-                }
-
-                i_ts_payload_size = p_ts->i_payload_end - p_ts->i_payload_start;
-            }
-            while(i_ts_payload_size + i_dummy < PES_HEADER_SIZE);
-
-            /* This last TS packet is partly header, partly payload, so just
-               copy the header part */
-            memcpy(p_pes->p_pes_header_save + i_dummy,
-                   &p_ts->buffer[p_ts->i_payload_start],
-                   PES_HEADER_SIZE - i_dummy);
-
-            /* The header must be read in the buffer not in any TS packet */
-            p_pes->p_pes_header = p_pes->p_pes_header_save;
-
-            /* Get the PES size if defined */
-            if( (i_dummy = U16_AT(p_pes->p_pes_header + 4)) )
-            {
-                p_pes->i_pes_real_size = i_dummy + 6;
-            }
-        }
-
-        /* Now we have the part of the PES header we were interested in:
-           p_pes_header and i_pes_real_size ; we can parse it */
-        input_ParsePES( p_input, p_es_descriptor );
-    }
-
-    /* If we are at the beginning of a new PES packet, we must fetch a new
-       PES buffer to begin with the reassembly of this PES packet. This is
-       also here that we can synchronise with the stream if we we lost
-       packets or if the decoder has just started */
-    if( b_unit_start )
-    {
-        p_last_pes = p_pes;
-
-        /* Get a new one PES from the PES netlist. */
-        if( (p_pes = input_NetlistGetPES( p_input )) == (NULL) )
-        {
-            /* PES netlist is empty ! */
-            p_input->b_error = 1;
-        }
-        else
-        {
-            //intf_DbgMsg("New PES packet %p (first TS: %p)\n", p_pes, p_ts_packet);
-
-            /* Init the PES fields so that the first TS packet could be
-             * correctly added to the PES packet (see below) */
-            p_pes->p_first_ts = p_ts_packet;
-            p_pes->p_last_ts = NULL;
-
-            /* If the last pes packet was null, this means that the
-             * synchronization was lost and so warn the decoder that he
-             * will have to find a way to recover */
-            if( !p_last_pes )
-                p_pes->b_data_loss = 1;
-
-            /* Read the b_random_access flag status and then reinit it */
-            p_pes->b_random_access = p_es_descriptor->b_random;
-            p_es_descriptor->b_random = 0;
-        }
-
-        /* If the PES header fits in the first TS packet, we can
-         * already set p_pes->p_pes_header, and in all cases we
-        * set p_pes->i_pes_real_size */
-        if( p_ts_packet->i_payload_end - p_ts_packet->i_payload_start
-                >= PES_HEADER_SIZE )
-        {
-            p_pes->p_pes_header = &(p_ts_packet->buffer[p_ts_packet->i_payload_start]);
-            if( (i_dummy = U16_AT(p_pes->p_pes_header + 4)) )
-            {
-                p_pes->i_pes_real_size = i_dummy + 6;
-            }
-        }
-    }
-
-
-    /* If we are synchronized with the stream, and so if we are ready to
-       receive correctly the data, add the TS packet to the current PES
-       packet */
-    if( p_pes != NULL )
-    {
-        //intf_DbgMsg("Adding TS %p to PES %p\n", p_ts_packet, p_pes);
-
-        /* Size of the payload carried in the TS packet */
-        i_ts_payload_size = p_ts_packet->i_payload_end -
-                            p_ts_packet->i_payload_start;
-
-        /* Update the relations between the TS packets */
-        p_ts_packet->p_prev_ts = p_pes->p_last_ts;
-        p_ts_packet->p_next_ts = NULL;
-        if( p_pes->i_ts_packets != 0 )
-        {
-            /* Regarder si il serait pas plus efficace de ne creer que
-             * les liens precedent->suivant pour le moment, et les
-             * liens suivant->precedent quand le paquet est termine */
-            /* Otherwise it is the first TS packet. */
-            p_pes->p_last_ts->p_next_ts = p_ts_packet;
-        }
-        /* Now add the TS to the PES packet */
-        p_pes->p_last_ts = p_ts_packet;
-        p_pes->i_ts_packets++;
-        p_pes->i_pes_size += i_ts_payload_size;
-
-        /* Stats */
-#ifdef STATS
-        i_dummy = p_ts_packet->i_payload_end - p_ts_packet->i_payload_start;
-        p_es_descriptor->c_payload_bytes += i_dummy;
-        p_input->c_payload_bytes += i_dummy;
-#endif
-
-        /* We can check if the packet is finished */
-        if( p_pes->i_pes_size == p_pes->i_pes_real_size )
-        {
-            /* The packet is finished, parse it */
-            input_ParsePES( p_input, p_es_descriptor );
-
-            /* Tell the Demux we have parsed this PES, no need to redo it */
-            p_pes = NULL;
-        }
-    }
-    else
+    while( !p_input->b_die )
     {
-        /* Since we don't use the TS packet to build a PES packet, we don't
-           need it anymore, so give it back to the netlist */
-        //intf_DbgMsg("Trashing TS %p: no PES being build\n", p_ts_packet);
-        input_NetlistFreeTS( p_input, p_ts_packet );
+        /* Sleep a while */
+        msleep( INPUT_IDLE_SLEEP );
     }
-
-#undef p_pes
 }
 
 /*****************************************************************************
- * input_DemuxTS: first step of demultiplexing: the TS header
- *****************************************************************************
- * Stream must also only contain PES and PSI, so PID must have been filtered
+ * EndThread: end the input thread
  *****************************************************************************/
-static __inline__ void input_DemuxTS( input_thread_t *p_input,
-                                      ts_packet_t *p_ts_packet,
-                                      es_descriptor_t *p_es_descriptor )
+static void EndThread( input_thread_t * p_input )
 {
-    int         i_dummy;
-    boolean_t   b_adaption;                     /* Adaption field is present */
-    boolean_t   b_payload;                         /* Packet carries payload */
-    boolean_t   b_unit_start;          /* A PSI or a PES start in the packet */
-    boolean_t   b_trash = 0;                 /* Must the packet be trashed ? */
-    boolean_t   b_lost = 0;                     /* Was there a packet lost ? */
-
-    ASSERT(p_input);
-    ASSERT(p_ts_packet);
-    ASSERT(p_es_descriptor);
-
-#define p (p_ts_packet->buffer)
-
-    //intf_DbgMsg("input debug: TS-demultiplexing packet %p, pid %d, number %d\n",
-    //            p_ts_packet, U16_AT(&p[1]) & 0x1fff, p[3] & 0x0f);
-
-#ifdef STATS
-    p_es_descriptor->c_packets++;
-    p_es_descriptor->c_bytes += TS_PACKET_SIZE;
-#endif
+    int *       pi_status;                                  /* thread status */
+    int         i_es_loop;                                       /* es index */
 
-    /* Extract flags values from TS common header. */
-    b_unit_start = (p[1] & 0x40);
-    b_adaption = (p[3] & 0x20);
-    b_payload = (p[3] & 0x10);
+    /* Store status */
+    pi_status = p_input->pi_status;
+    *pi_status = THREAD_END;
 
-    /* Extract adaption field informations if any */
-    if( !b_adaption )
-    {
-        /* We don't have any adaptation_field, so payload start immediately
-           after the 4 byte TS header */
-        p_ts_packet->i_payload_start = 4;
-    }
-    else
+    /* Destroy all decoder threads */
+    for( i_es_loop = 0;
+         (i_es_loop < INPUT_MAX_ES)
+            && (p_input->pp_selected_es[i_es_loop] != NULL) ;
+         i_es_loop++ )
     {
-        /* p[4] is adaptation_field_length minus one */
-        p_ts_packet->i_payload_start = 5 + p[4];
-
-        /* The adaption field can be limited to the adaptation_field_length byte,
-           so that there is nothing to do: skip this possibility */
-        if( p[4] )
-        {
-            /* If the packet has both adaptation_field and payload, adaptation_field
-               cannot be more than 182 bytes long; if there is only an
-               adaptation_field, it must fill the next 183 bytes. */
-            if( b_payload ? (p[4] > 182) : (p[4] != 183) )
-            {
-                intf_DbgMsg("input debug: invalid TS adaptation field (%p)\n",
-                            p_ts_packet);
-#ifdef STATS
-                p_es_descriptor->c_invalid_packets++;
-#endif
-                b_trash = 1;
-            }
-
-            /* No we are sure that the byte containing flags is present: read it */
-            else
-            {
-                /* discontinuity_indicator */
-                if( p[5] & 0x80 )
-                {
-                    intf_DbgMsg("discontinuity_indicator encountered by TS demux " \
-                                "(position read: %d, saved: %d)\n", p[5] & 0x80,
-                                p_es_descriptor->i_continuity_counter);
-
-                    /* If the PID carries the PCR, there will be a system time-base
-                       discontinuity. We let the PCR decoder handle that. */
-                    p_es_descriptor->b_discontinuity = 1;
+        p_input->pp_selected_es[i_es_loop]->p_decoder_fifo->b_die = 1;
+        /* Make sure the thread leaves the GetByte() function */
+        vlc_mutex_lock( &p_input->pp_selected_es[i_es_loop]->p_decoder_fifo->data_lock);
+        vlc_cond_signal( &p_input->pp_selected_es[i_es_loop]->p_decoder_fifo->data_wait );
+        vlc_mutex_unlock( &p_input->pp_selected_es[i_es_loop]->p_decoder_fifo->data_lock );
 
-                    /* There also may be a continuity_counter discontinuity:
-               resynchronise our counter with the one of the stream */
-                    p_es_descriptor->i_continuity_counter = (p[3] & 0x0f) - 1;
-                }
-
-                /* random_access_indicator */
-                p_es_descriptor->b_random |= p[5] & 0x40;
-
-                /* If this is a PCR_PID, and this TS packet contains a PCR,
-           we pass it along to the PCR decoder. */
-                if( (p_es_descriptor->b_pcr) && (p[5] & 0x10) )
-                {
-                    /* There should be a PCR field in the packet, check if the
-               adaption field is long enough to carry it */
-                    if( p[4] >= 7 )
-                    {
-                        /* Call the PCR decoder */
-                        input_PcrDecode( p_input, p_es_descriptor, &p[6] );
-                    }
-                }
-            }
-        }
+        /* Waiting for the thread to exit */
+        vlc_thread_join( p_input->pp_selected_es[i_es_loop]->thread_id );
+        free( p_input->pp_selected_es[i_es_loop]->p_decoder_fifo );
     }
 
-    /* Check the continuity of the stream. */
-    i_dummy = ((p[3] & 0x0f) - p_es_descriptor->i_continuity_counter) & 0x0f;
-    if( i_dummy == 1 )
-    {
-        /* Everything is ok, just increase our counter */
-        p_es_descriptor->i_continuity_counter++;
-    }
-    else
-    {
-        if( !b_payload && i_dummy == 0 )
-        {
-            /* This is a packet without payload, this is allowed by the draft
-               As there is nothing interesting in this packet (except PCR that
-               have already been handled), we can trash the packet. */
-            intf_DbgMsg("Packet without payload received by TS demux\n");
-            b_trash = 1;
-        }
-        else if( i_dummy <= 0 )
-        {
-            /* Duplicate packet: mark it as being to be trashed. */
-            intf_DbgMsg("Duplicate packet received by TS demux\n");
-            b_trash = 1;
-        }
-        else if( p_es_descriptor->i_continuity_counter == 0xFF )
-        {
-            /* This means that the packet is the first one we receive for this
-               ES since the continuity counter ranges between 0 and 0x0F
-               excepts when it has been initialized by the input: Init the
-               counter to the correct value. */
-            intf_DbgMsg("First packet for PID %d received by TS demux\n",
-                        p_es_descriptor->i_id);
-            p_es_descriptor->i_continuity_counter = (p[3] & 0x0f);
-        }
-        else
-        {
-            /* This can indicate that we missed a packet or that the
-               continuity_counter wrapped and we received a dup packet: as we
-               don't know, do as if we missed a packet to be sure to recover
-               from this situation */
-            intf_DbgMsg("Packet lost by TS demux: current %d, packet %d\n",
-                        p_es_descriptor->i_continuity_counter & 0x0f,
-                        p[3] & 0x0f);
-            b_lost = 1;
-            p_es_descriptor->i_continuity_counter = p[3] & 0x0f;
-        }
-    }
+    /* Free demultiplexer's data */
 
-    /* Trash the packet if it has no payload or if it is bad */
-    if( b_trash )
-    {
-        input_NetlistFreeTS( p_input, p_ts_packet );
-#ifdef STATS
-        p_input->c_packets_trashed++;
-#endif
-    }
-    else
-    {
-        if( p_es_descriptor->b_psi )
-        {
-            /* The payload contains PSI tables */
-            input_DemuxPSI( p_input, p_ts_packet, p_es_descriptor,
-                            b_unit_start, b_lost );
-        }
-        else
-        {
-            /* The payload carries a PES stream */
-            input_DemuxPES( p_input, p_ts_packet, p_es_descriptor,
-                            b_unit_start, b_lost );
-        }
-    }
-
-#undef p
+    /* Update status */
+    *pi_status = THREAD_OVER;
 }
 
 /*****************************************************************************
- * input_SortPacket: find out whether we need that packet
+ * NetworkOpen : open a network socket descriptor
  *****************************************************************************/
-static __inline__ void input_SortPacket( input_thread_t *p_input,
-                                         ts_packet_t *p_ts_packet )
+static void NetworkOpen( input_thread_t * p_input )
 {
-    int             i_current_pid;
-    int             i_es_loop;
+    /* straight copy & paste of input_network.c of input-I */
 
-    /* Verify that sync_byte, error_indicator and scrambling_control are
-       what we expected. */
-    if( !(p_ts_packet->buffer[0] == 0x47) || (p_ts_packet->buffer[1] & 0x80) ||
-        (p_ts_packet->buffer[3] & 0xc0) )
-    {
-        intf_DbgMsg("input debug: invalid TS header (%p)\n", p_ts_packet);
-    }
-    else
-    {
-        /* Get the PID of the packet. Note that ntohs is needed, for endianness
-           purposes (see man page). */
-        i_current_pid = U16_AT(&p_ts_packet->buffer[1]) & 0x1fff;
-
-        //intf_DbgMsg("input debug: pid %d received (%p)\n",
-        //            i_current_pid, p_ts_packet);
-
-        /* Lock current ES state. */
-        vlc_mutex_lock( &p_input->es_lock );
-
-    /* Verify that we actually want this PID. */
-        for( i_es_loop = 0; i_es_loop < INPUT_MAX_SELECTED_ES; i_es_loop++ )
-        {
-            if( p_input->pp_selected_es[i_es_loop] != NULL)
-            {
-                if( (*p_input->pp_selected_es[i_es_loop]).i_id
-                     == i_current_pid )
-                {
-                    /* Don't need the lock anymore, since the value pointed
-                       out by p_input->pp_selected_es[i_es_loop] can only be
-                       modified from inside the input_thread (by the PSI
-                       decoder): interface thread is only allowed to modify
-                       the pp_selected_es table */
-                    vlc_mutex_unlock( &p_input->es_lock );
-
-                    /* We're interested. Pass it to the demultiplexer. */
-                    input_DemuxTS( p_input, p_ts_packet,
-                                   p_input->pp_selected_es[i_es_loop] );
-                    return;
-                }
-            }
-            else
-            {
-                /* pp_selected_es should not contain any hole. */
-                break;
-            }
-        }
-        vlc_mutex_unlock( &p_input->es_lock );
-    }
-
-    /* We weren't interested in receiving this packet. Give it back to the
-       netlist. */
-    //intf_DbgMsg("SortPacket: freeing unwanted TS %p (pid %d)\n", p_ts_packet,
-    //                 U16_AT(&p_ts_packet->buffer[1]) & 0x1fff);
-    input_NetlistFreeTS( p_input, p_ts_packet );
-#ifdef STATS
-    p_input->c_packets_trashed++;
-#endif
+    /* We cannot rewind nor lseek() */
+    p_input->stream.b_seekable = 0;
+    /* We cannot control the pace */
+    p_input->stream.b_pace_control = 0;
 }
 
 /*****************************************************************************
- * input_ReadPacket: reads a packet from the network or the file
+ * FileOpen : open a file descriptor
  *****************************************************************************/
-static __inline__ int input_ReadPacket( input_thread_t *p_input )
+static void FileOpen( input_thread_t * p_input )
 {
-    int                 i_base_index; /* index of the first free iovec */
-    int                 i_current_index;
-    int                 i_packet_size;
-#ifdef INPUT_LIFO_TS_NETLIST
-    int                 i_meanwhile_released;
-    int                 i_currently_removed;
-#endif
-    ts_packet_t *       p_ts_packet;
-
-    /* In this function, we only care about the TS netlist. PES netlist
-     * is for the demultiplexer. */
-#ifdef INPUT_LIFO_TS_NETLIST
-    i_base_index = p_input->netlist.i_ts_index;
+    struct stat         stat_info;
 
-    /* Verify that we still have packets in the TS netlist */
-    if( (INPUT_MAX_TS + INPUT_TS_READ_ONCE - 1 - p_input->netlist.i_ts_index) <= INPUT_TS_READ_ONCE )
-    {
-        intf_ErrMsg("input error: TS netlist is empty !\n");
-        return( -1 );
-    }
+#define p_config    p_input->p_config
 
-#else /* FIFO netlist */
-    i_base_index = p_input->netlist.i_ts_start;
-    if( p_input->netlist.i_ts_start + INPUT_TS_READ_ONCE -1 > INPUT_MAX_TS )
+    if( stat( p_config->p_source, &stat_info ) == (-1) )
     {
-        /* The netlist is split in 2 parts. We must gather them to consolidate
-           the FIFO (we make the loop easily in having the same iovec at the far
-           end and in the beginning of netlist_free).
-           That's why the netlist is (INPUT_MAX_TS +1) + (INPUT_TS_READ_ONCE -1)
-           large. */
-        memcpy( p_input->netlist.p_ts_free + INPUT_MAX_TS + 1,
-                p_input->netlist.p_ts_free,
-                (p_input->netlist.i_ts_start + INPUT_TS_READ_ONCE - 1 - INPUT_MAX_TS)
-                  * sizeof(struct iovec) );
-    }
-
-    /* Verify that we still have packets in the TS netlist */
-    if( ((p_input->netlist.i_ts_end -1 - p_input->netlist.i_ts_start) & INPUT_MAX_TS) <= INPUT_TS_READ_ONCE )
-    {
-        intf_ErrMsg("input error: TS netlist is empty !\n");
-        return( -1 );
+        intf_ErrMsg("Cannot stat() file %s (%s)", p_config->p_source,
+                    strerror(errno));
+        p_input->b_error = 1;
+        return;
     }
-#endif /* FIFO netlist */
 
-    /* Scatter read the buffer. */
-    i_packet_size = (*p_input->p_Read)( p_input,
-                           &p_input->netlist.p_ts_free[i_base_index],
-                           INPUT_TS_READ_ONCE );
-    if( i_packet_size == (-1) )
-    {
-#if 0
-        intf_DbgMsg("Read packet %d %p %d %d\n", i_base_index,
-                    &p_input->netlist.p_ts_free[i_base_index],
-                    p_input->netlist.i_ts_start,
-                    p_input->netlist.i_ts_end);
-#endif
-        intf_ErrMsg("input error: readv() failed (%s)\n", strerror(errno));
-        return( -1 );
-    }
+    vlc_mutex_lock( &p_input->stream.stream_lock );
 
-    if( i_packet_size == 0 )
-    {
-        /* No packet has been received, so stop here. */
-        return( 0 );
-    }
+    /* If we are here we can control the pace... */
+    p_input->stream.b_pace_control = 1;
 
-    /* Demultiplex the TS packets (1..INPUT_TS_READ_ONCE) received. */
-    for( i_current_index = i_base_index;
-         (i_packet_size -= TS_PACKET_SIZE) >= 0;
-         i_current_index++ )
+    if( S_ISREG(stat_info.st_mode) || S_ISCHR(stat_info.st_mode)
+         || S_ISBLK(stat_info.st_mode) )
     {
-        /* BTW, something REALLY bad could happen if we receive packets with
-           a wrong size. */
-        p_ts_packet = (ts_packet_t*)(p_input->netlist.p_ts_free[i_current_index].iov_base);
-        /* Don't cry :-), we are allowed to do that cast, because initially,
-           our buffer was malloc'ed with sizeof(ts_packet_t) */
-
-        /* Find out if we need this packet and demultiplex. */
-        input_SortPacket( p_input /* for current PIDs and netlist */,
-                          p_ts_packet);
+        p_input->stream.b_seekable = 1;
+        p_input->stream.i_size = stat_info.st_size;
     }
-
-    if( i_packet_size > 0 )
+    else if( S_ISFIFO(stat_info.st_mode) || S_ISSOCK(stat_info.st_mode) )
     {
-        intf_ErrMsg("input error: wrong size\n");
-        return( -1 );
-    }
-
-    /* Remove the TS packets we have just filled from the netlist */
-#ifdef INPUT_LIFO_TS_NETLIST
-    /* We need to take a lock here while we're calculating index positions. */
-    vlc_mutex_lock( &p_input->netlist.lock );
-
-    i_meanwhile_released = i_base_index - p_input->netlist.i_ts_index;
-    if( i_meanwhile_released )
-    {
-        /* That's where it becomes funny :-). Since we didn't take locks for
-           efficiency reasons, other threads (including ourselves, with
-           input_DemuxPacket) might have released packets to the netlist.
-           So we have to copy these iovec where they should go.
-
-           BTW, that explains why the TS netlist is
-           (INPUT_MAX_TS +1) + (TS_READ_ONCE -1) large. */
-
-        i_currently_removed = i_current_index - i_base_index;
-        if( i_meanwhile_released < i_currently_removed )
-        {
-            /* Copy all iovecs in that case */
-            memcpy( &p_input->netlist.p_ts_free[p_input->netlist.i_ts_index]
-                     + i_currently_removed,
-                    &p_input->netlist.p_ts_free[p_input->netlist.i_ts_index],
-                    i_meanwhile_released * sizeof(struct iovec) );
-        }
-        else
-        {
-            /* We have fewer places than items, so we only move
-               i_currently_removed of them. */
-            memcpy( &p_input->netlist.p_ts_free[i_base_index],
-                    &p_input->netlist.p_ts_free[p_input->netlist.i_ts_index],
-                    i_currently_removed * sizeof(struct iovec) );
-        }
-
-        /* Update i_netlist_index with the information gathered above. */
-        p_input->netlist.i_ts_index += i_currently_removed;
+        p_input->stream.b_seekable = 0;
+        p_input->stream.i_size = 0;
     }
     else
     {
-        /* Nothing happened. */
-        p_input->netlist.i_ts_index = i_current_index;
-    }
-
-    vlc_mutex_unlock( &p_input->netlist.lock );
-
-#else /* FIFO netlist */
-    /* & is modulo ; that's where we make the loop. */
-    p_input->netlist.i_ts_start = i_current_index & INPUT_MAX_TS;
-#endif
-
-#ifdef STATS
-    p_input->c_packets_read += i_current_index - i_base_index;
-    p_input->c_bytes += (i_current_index - i_base_index) * TS_PACKET_SIZE;
-#endif
-    return( 0 );
-}
-
-/*****************************************************************************
- * RunThread: main thread loop
- *****************************************************************************
- * Thread in charge of processing the network packets and demultiplexing.
- *****************************************************************************/
-static void RunThread( input_thread_t *p_input )
-{
-    /*
-     * Initialize thread and free configuration
-     */
-    p_input->b_error = InitThread( p_input );
-    if( p_input->b_error )
-    {
-        free( p_input );                               /* destroy descriptor */
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+        intf_ErrMsg("Unknown file type");
+        p_input->b_error = 1;
         return;
     }
 
-    /*
-     * Main loop
-     */
-    intf_DbgMsg("\n");
-    while( !p_input->b_die && !p_input->b_error )
-    {
-        /* Scatter read the UDP packet from the network or the file. */
-        if( (input_ReadPacket( p_input )) == (-1) )
-        {
-            /* FIXME??: Normally, a thread can't kill itself, but we don't have
-             * any method in case of an error condition ... */
-            p_input->b_error = 1;
-        }
-
-#ifdef STATS
-        p_input->c_loops++;
-#endif
-    }
-
-    /*
-     * Error loop
-     */
-    if( p_input->b_error )
-    {
-        ErrorThread( p_input );
-    }
-
-    /* End of thread */
-    EndThread( p_input );
-    intf_DbgMsg("thread end\n");
-}
-
+    p_input->stream.i_tell = 0;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
 
-/*****************************************************************************
- * ErrorThread: RunThread() error loop
- *****************************************************************************
- * This function is called when an error occured during thread main's loop.
- *****************************************************************************/
-static void ErrorThread( input_thread_t *p_input )
-{
-    /* Wait until a `die' order */
-    intf_DbgMsg("\n");
-    while( !p_input->b_die )
+    intf_Msg( "Opening file %s", p_config->p_source );
+    if( (p_input->i_handle = open( p_config->p_source,
+                                   /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
     {
-        /* Sleep a while */
-        msleep( VOUT_IDLE_SLEEP );
-    }
-}
-
-/*****************************************************************************
- * EndThread: end the input thread
- *****************************************************************************/
-static void EndThread( input_thread_t * p_input )
-{
-    int *       pi_status;                                  /* threas status */
-    int         i_es_loop;                                       /* es index */
-
-    /* Store status */
-    intf_DbgMsg("\n");
-    pi_status = p_input->pi_status;
-    *pi_status = THREAD_END;
-
-#ifdef STATS
-    intf_Msg("input stats: Done %d loops\n", p_input->c_loops);
-    intf_Msg("input stats: Read %d bytes (payload : %d)\n", p_input->c_bytes,
-             p_input->c_payload_bytes);
-    intf_Msg("input stats: Read %d packets (trashed : %d)\n",
-             p_input->c_packets_read, p_input->c_packets_trashed);
-#endif
-
-    /* Close input method */
-    p_input->p_Close( p_input );
-
-    /* Destroy all decoder threads */
-    for( i_es_loop = 0;
-         (i_es_loop < INPUT_MAX_ES) && (p_input->pp_selected_es[i_es_loop] != NULL) ;
-         i_es_loop++ )
-    {
-        switch( p_input->pp_selected_es[i_es_loop]->i_type )
-        {
-        case MPEG1_VIDEO_ES:
-        case MPEG2_VIDEO_ES:
-            vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
-            break;
-        case MPEG1_AUDIO_ES:
-        case MPEG2_AUDIO_ES:
-            adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) );
-            break;
-        case AC3_AUDIO_ES:
-            ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
-            break;
-        case LPCM_AUDIO_ES:
-            lpcmdec_DestroyThread((lpcmdec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
-            break;
-        case DVD_SPU_ES:
-            spudec_DestroyThread( (spudec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
-            break;
-        case 0:
-            /* Special streams for the PSI decoder, PID 0 and 1 */
-            break;
-#ifdef DEBUG
-        default:
-            intf_DbgMsg("error: unknown decoder type %d\n", p_input->pp_selected_es[i_es_loop]->i_type );
-            break;
-#endif
-        }
+        intf_ErrMsg("Cannot open file (%s)", strerror(errno));
+        p_input->b_error = 1;
+        return;
     }
 
-    input_NetlistEnd( p_input );                            /* clean netlist */
-    input_PsiEnd( p_input );                        /* clean PSI information */
-    input_PcrEnd( p_input );                        /* clean PCR information */
-    free( p_input );                          /* free input_thread structure */
-
-    /* Update status */
-    *pi_status = THREAD_OVER;
+#undef p_config
 }
-
diff --git a/src/input/input.h b/src/input/input.h
new file mode 100644 (file)
index 0000000..8fbfa58
--- /dev/null
@@ -0,0 +1,47 @@
+/* Communication plugin -> input */
+
+#define INPUT_READ_ONCE     7   /* We live in a world dominated by Ethernet. *
+                                 * Ethernet MTU is 1500 bytes, so in a UDP   *
+                                 * packet we can put : 1500/188 = 7 TS       *
+                                 * packets. Have a nice day and merry Xmas.  */
+
+/*****************************************************************************
+ * input_capabilities_t
+ *****************************************************************************
+ * This structure gives pointers to the useful methods of the plugin
+ *****************************************************************************/
+typedef struct input_capabilities_s
+{
+    /* Plugin properties */
+    int                     i_weight; /* for a given stream type, the plugin *
+                                       * with higher weight will be used     */
+
+    /* Init/End */
+    int                  (* pf_probe)( struct input_thread_s * );
+    void                 (* pf_init)( struct input_thread_s * );
+    void                 (* pf_end)( struct input_thread_s * );
+
+    /* Read & Demultiplex */
+    void                 (* pf_read)( struct input_thread_s *,
+                          struct data_packet_s * pp_packets[INPUT_READ_ONCE] );
+    void                 (* pf_demux)( struct input_thread_s *,
+                                       struct data_packet_s * );
+
+    /* Packet management facilities */
+    struct data_packet_s *(* pf_new_packet)( void *, size_t );
+    void                 (* pf_delete_packet)( void *,
+                                               struct data_packet_s * );
+    void                 (* pf_delete_pes)( void *, struct pes_packet_s * );
+
+    /* Stream control capabilities */
+    int                  (* pf_rewind)( struct input_thread_s * );
+                                           /* NULL if we don't support going *
+                                            * backwards (it's gonna be fun)  */
+    int                  (* pf_seek)( struct input_thread_s *, off_t );
+} input_capabilities_t;
+
+/*****************************************************************************
+ * Prototypes from input_ext-dec.c
+ *****************************************************************************/
+void InitBitstream  ( struct bit_stream_s *, struct decoder_fifo_s * );
+void NextDataPacket ( struct bit_stream_s * );
diff --git a/src/input/input_ctrl.c b/src/input/input_ctrl.c
deleted file mode 100644 (file)
index 0bcb6ab..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-/*****************************************************************************
- * input_ctrl.c: Decoder control
- * Controls the extraction and the decoding of the programs elements carried
- * within a stream.
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *          Benoît Steiner <benny@via.ecp.fr>
- *
- * 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 <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
-#include <stdio.h>
-#include <netinet/in.h>                                             /* ntohs */
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "intf_msg.h"
-#include "plugins.h"
-#include "debug.h"
-
-#include "input.h"
-#include "input_netlist.h"
-#include "decoder_fifo.h"
-
-#include "audio_output.h"                                   /* aout_thread_t */
-
-#include "audio_decoder.h"        /* audiodec_t (for audio_decoder_thread.h) */
-#include "audio_decoder_thread.h"                           /* adec_thread_t */
-
-#include "ac3_decoder.h"              /* ac3dec_t (for ac3_decoder_thread.h) */
-#include "ac3_decoder_thread.h"                           /* ac3dec_thread_t */
-
-#include "lpcm_decoder.h"
-#include "lpcm_decoder_thread.h"
-
-#include "video.h"                          /* picture_t (for video_output.h) */
-#include "video_output.h"                                   /* vout_thread_t */
-
-#include "vdec_idct.h"                     /* dctelem_t (for video_parser.h) */
-#include "vdec_motion.h"                  /* f_motion_t (for video_parser.h) */
-#include "vpar_blocks.h"                /* macroblock_t (for video_parser.h) */
-#include "vpar_headers.h"                 /* sequence_t (for video_parser.h) */
-#include "vpar_synchro.h"            /* video_synchro_t (for video_parser.h) */
-#include "video_parser.h"                                   /* vpar_thread_t */
-
-#include "spu_decoder.h"                                  /* spudec_thread_t */
-
-/*****************************************************************************
- * input_AddPgrmElem: Start the extraction and the decoding of a program element
- *****************************************************************************
- * Add the element given by its PID in the list of PID to extract and spawn
- * the decoding thread.
- * This function only modifies the table of selected es, but must NOT modify
- * the table of ES itself.
- *****************************************************************************/
-int input_AddPgrmElem( input_thread_t *p_input, int i_current_id )
-{
-    int i_es_loop, i_selected_es_loop;
-
-    /* Since this function is intended to be called by interface, lock the
-     * elementary stream structure. */
-    vlc_mutex_lock( &p_input->es_lock );
-
-    /* Find out which PID we need. */
-    for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
-    {
-        if( p_input->p_es[i_es_loop].i_id == i_current_id )
-        {
-            if( p_input->p_es[i_es_loop].p_dec != NULL )
-            {
-                /* We already have a decoder for that PID. */
-                vlc_mutex_unlock( &p_input->es_lock );
-                intf_ErrMsg("input error: PID %d already selected\n",
-                            i_current_id);
-                return( -1 );
-            }
-
-            intf_DbgMsg("Requesting selection of PID %d\n",
-                        i_current_id);
-
-            /* Find a free spot in pp_selected_es. */
-            for( i_selected_es_loop = 0; p_input->pp_selected_es[i_selected_es_loop] != NULL
-                  && i_selected_es_loop < INPUT_MAX_SELECTED_ES; i_selected_es_loop++ );
-
-            if( i_selected_es_loop == INPUT_MAX_SELECTED_ES )
-            {
-                /* array full */
-                vlc_mutex_unlock( &p_input->es_lock );
-                intf_ErrMsg("input error: MAX_SELECTED_ES reached: try increasing it in config.h\n");
-                return( -1 );
-            }
-
-            /* Don't decode PSI streams ! */
-            if( p_input->p_es[i_es_loop].b_psi )
-            {
-                intf_ErrMsg("input_error: trying to decode PID %d which is the one of a PSI\n", i_current_id);
-                vlc_mutex_unlock( &p_input->es_lock );
-                return( -1 );
-            }
-            else
-            {
-                /* Spawn the decoder. */
-                switch( p_input->p_es[i_es_loop].i_type )
-                {
-                    
-                    case AC3_AUDIO_ES:
-                        /* Spawn ac3 thread */
-                        if ( ((ac3dec_thread_t *)(p_input->p_es[i_es_loop].p_dec) =
-                            ac3dec_CreateThread(p_input)) == NULL )
-                        {
-                            intf_ErrMsg( "Could not start ac3 decoder\n" );
-                            vlc_mutex_unlock( &p_input->es_lock );
-                            return( -1 );
-                        }
-                        break;
-
-                            case LPCM_AUDIO_ES:
-                        /* Spawn lpcm thread */
-                        if ( ((lpcmdec_thread_t *)
-                              (p_input->p_es[i_es_loop].p_dec) =
-                              lpcmdec_CreateThread(p_input)) == NULL )
-                        {
-                            intf_ErrMsg( "LPCM Debug: Could not start "
-                                         "lpcm decoder\n" );
-                            vlc_mutex_unlock( &p_input->es_lock );
-                            return( -1 );
-                        }
-                        break;
-
-
-                    case DVD_SPU_ES:
-                        /* Spawn spu thread */
-                        if ( ((spudec_thread_t *)
-                              (p_input->p_es[i_es_loop].p_dec) =
-                              spudec_CreateThread(p_input)) == NULL )
-                        {
-                            intf_ErrMsg( "Could not start spu decoder\n" );
-                            vlc_mutex_unlock( &p_input->es_lock );
-                            return( -1 );
-                        }
-                        break;
-
-                    case MPEG1_AUDIO_ES:
-                    case MPEG2_AUDIO_ES:
-                        /* Spawn audio thread. */
-                        if( ((adec_thread_t*)(p_input->p_es[i_es_loop].p_dec) =
-                            adec_CreateThread( p_input )) == NULL )
-                        {
-                            intf_ErrMsg("Could not start audio decoder\n");
-                            vlc_mutex_unlock( &p_input->es_lock );
-                            return( -1 );
-                        }
-                        break;
-
-                    case MPEG1_VIDEO_ES:
-                    case MPEG2_VIDEO_ES:
-                        /* Spawn video thread. */
-                        if( ((vpar_thread_t*)(p_input->p_es[i_es_loop].p_dec) =
-                            vpar_CreateThread( p_input )) == NULL )
-                        {
-                            intf_ErrMsg("Could not start video parser\n");
-                            vlc_mutex_unlock( &p_input->es_lock );
-                            return( -1 );
-                        }
-                        break;
-
-                    default:
-                        /* That should never happen. */
-                        intf_DbgMsg( "input error: unknown stream (0x%.2x)\n",
-                                    p_input->p_es[i_es_loop].i_type);
-                        vlc_mutex_unlock( &p_input->es_lock );
-                        return( -1 );
-                        break;
-                }
-
-                /* Initialise the demux */
-                p_input->p_es[i_es_loop].p_pes_packet = NULL;
-                p_input->p_es[i_es_loop].i_continuity_counter = 0xff;
-                p_input->p_es[i_es_loop].b_random = 0;
-
-                /* Mark stream to be demultiplexed. */
-                intf_DbgMsg( "Stream %d added in %d\n",
-                             i_current_id, i_selected_es_loop);
-                p_input->pp_selected_es[i_selected_es_loop] =
-                                                 &p_input->p_es[i_es_loop];
-                vlc_mutex_unlock( &p_input->es_lock );
-                return( 0 );
-            }
-        }
-    }
-
-    /* We haven't found this PID in the current stream. */
-    vlc_mutex_unlock( &p_input->es_lock );
-    intf_ErrMsg("input error: can't find PID %d\n", i_current_id);
-    return( -1 );
-}
-
-/*****************************************************************************
- * input_DelPgrmElem: Stop the decoding of a program element
- *****************************************************************************
- * Stop the extraction of the element given by its PID and kill the associated
- * decoder thread
- * This function only modifies the table of selected es, but must NOT modify
- * the table of ES itself.
- *****************************************************************************/
-int input_DelPgrmElem( input_thread_t *p_input, int i_current_id )
-{
-    int i_selected_es_loop, i_last_selected;
-
-    /* Since this function is intended to be called by interface, lock the
-       structure. */
-    vlc_mutex_lock( &p_input->es_lock );
-
-    /* Find out which PID we need. */
-    for( i_selected_es_loop = 0; i_selected_es_loop < INPUT_MAX_SELECTED_ES;
-         i_selected_es_loop++ )
-    {
-        if( p_input->pp_selected_es[i_selected_es_loop] )
-        {
-            if( p_input->pp_selected_es[i_selected_es_loop]->i_id == i_current_id )
-            {
-                if( !(p_input->pp_selected_es[i_selected_es_loop]->p_dec) )
-                {
-                    /* We don't have a decoder for that PID. */
-                    vlc_mutex_unlock( &p_input->es_lock );
-                    intf_ErrMsg("input error: PID %d already deselected\n",
-                                i_current_id);
-                    return( -1 );
-                }
-
-                intf_DbgMsg("input debug: requesting termination of PID %d\n",
-                            i_current_id);
-
-                /* Cancel the decoder. */
-                switch( p_input->pp_selected_es[i_selected_es_loop]->i_type )
-                {
-                    case AC3_AUDIO_ES:
-                        ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
-                        break;
-                       
-                    case LPCM_AUDIO_ES:
-                        lpcmdec_DestroyThread( (lpcmdec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
-                        break;
-
-                    case DVD_SPU_ES:
-                        spudec_DestroyThread( (spudec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
-                        break;
-
-                    case MPEG1_AUDIO_ES:
-                    case MPEG2_AUDIO_ES:
-                        adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
-                        break;
-
-                    case MPEG1_VIDEO_ES:
-                    case MPEG2_VIDEO_ES:
-                        vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) /*, NULL */ );
-                        break;
-                }
-
-                /* Unmark stream. */
-                p_input->pp_selected_es[i_selected_es_loop]->p_dec = NULL;
-
-                /* Find last selected stream. */
-                for( i_last_selected = i_selected_es_loop;
-                        p_input->pp_selected_es[i_last_selected]
-                        && i_last_selected < INPUT_MAX_SELECTED_ES;
-                     i_last_selected++ );
-
-                /* Exchange streams. */
-                p_input->pp_selected_es[i_selected_es_loop] =
-                            p_input->pp_selected_es[i_last_selected];
-                p_input->pp_selected_es[i_last_selected] = NULL;
-
-                vlc_mutex_unlock( &p_input->es_lock );
-                return( 0 );
-            }
-        }
-    }
-
-    /* We haven't found this PID in the current stream. */
-    vlc_mutex_unlock( &p_input->es_lock );
-    intf_ErrMsg("input error: can't find PID %d\n", i_current_id);
-    return( -1 );
-}
-
-
-
-/*****************************************************************************
- * input_IsElemRecv: Test if an element given by its PID is currently received
- *****************************************************************************
- * Cannot return the position of the es in the pp_selected_es, for it can
- * change once we have released the lock
- *****************************************************************************/
-boolean_t input_IsElemRecv( input_thread_t *p_input, int i_id )
-{
-  boolean_t b_is_recv = 0;
-    int i_index = 0;
-
-   /* Since this function is intended to be called by interface, lock the
-       structure. */
-    vlc_mutex_lock( &p_input->es_lock );
-
-    /* Scan the table */
-    while( i_index < INPUT_MAX_SELECTED_ES && !p_input->pp_selected_es[i_index] )
-    {
-      if( p_input->pp_selected_es[i_index]->i_id == i_id )
-      {
-        b_is_recv = 1;
-        break;
-      }
-    }
-
-    /* Unlock the structure */
-    vlc_mutex_unlock( &p_input->es_lock );
-
-    return( b_is_recv );
-}
diff --git a/src/input/input_ctrl.h b/src/input/input_ctrl.h
deleted file mode 100644 (file)
index fa47875..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*****************************************************************************
- * input_ctrl.h: Decodeur control
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Requires:
- *  "config.h"
- *  "common.h"
- *  "mtime.h"
- *****************************************************************************/
-
-
-
-
-
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int input_AddPgrmElem( input_thread_t *p_input, int i_current_pid );
-int input_DelPgrmElem( input_thread_t *p_input, int i_current_pid );
-boolean_t input_IsElemRecv( input_thread_t *p_input, int i_pid );
diff --git a/src/input/input_ext-dec.c b/src/input/input_ext-dec.c
new file mode 100644 (file)
index 0000000..d8f0d71
--- /dev/null
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ * input_ext-dec.c: services to the decoders
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000 VideoLAN
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h"
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+#include "input.h"
+
+/*****************************************************************************
+ * InitBitstream: initialize a bit_stream_t structure
+ *****************************************************************************/
+void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo )
+{
+    p_bit_stream->p_decoder_fifo = p_fifo;
+    p_bit_stream->pf_next_data_packet = NextDataPacket;
+
+    /* Get the first data packet. */
+    vlc_mutex_lock( &p_fifo->data_lock );
+    while ( DECODER_FIFO_ISEMPTY( *p_fifo ) )
+    {
+        if ( p_fifo->b_die )
+        {
+            vlc_mutex_unlock( &p_fifo->data_lock );
+            return;
+        }
+        vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+    }
+    p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first;
+    p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
+    p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
+    p_bit_stream->fifo.buffer = 0;
+    p_bit_stream->fifo.i_available = 0;
+    vlc_mutex_unlock( &p_fifo->data_lock );
+}
+
+/*****************************************************************************
+ * NextDataPacket: go to the next data packet
+ *****************************************************************************/
+void NextDataPacket( bit_stream_t * p_bit_stream )
+{
+    WORD_TYPE           buffer_left;
+    /* FIXME : not portable in a 64bit environment */
+    int                 i_bytes_left;
+    decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
+
+    /* Buffer used at the end of a decoder thread, to give it zero
+     * values if needed. */
+    static byte_t       p_zero[64] = { 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0, 0 };
+
+    /* Put the remaining bytes (not aligned on a word boundary) in a
+     * temporary buffer. */
+    i_bytes_left = p_bit_stream->p_end - p_bit_stream->p_byte;
+    buffer_left = *((WORD_TYPE *)p_bit_stream->p_end - 1);
+
+    /* We are looking for the next data packet that contains real data,
+     * and not just a PES header */
+    do
+    {
+        /* We were reading the last data packet of this PES packet... It's
+         * time to jump to the next PES packet */
+        if( p_bit_stream->p_data->p_next == NULL )
+        {
+            /* We are going to read/write the start and end indexes of the
+             * decoder fifo and to use the fifo's conditional variable,
+             * that's why we need to take the lock before. */
+            vlc_mutex_lock( &p_fifo->data_lock );
+
+            /* Is the input thread dying ? */
+            if( p_fifo->b_die )
+            {
+                vlc_mutex_unlock( &p_fifo->data_lock );
+                p_bit_stream->p_byte = p_zero;
+                p_bit_stream->p_end = &p_zero[sizeof(p_zero) - 1];
+                return;
+            }
+
+            /* We should increase the start index of the decoder fifo, but
+             * if we do this now, the input thread could overwrite the
+             * pointer to the current PES packet, and we weren't able to
+             * give it back to the netlist. That's why we free the PES
+             * packet first. */
+            p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
+                                   DECODER_FIFO_START( *p_fifo ) );
+            DECODER_FIFO_INCSTART( *p_fifo );
+
+            while( DECODER_FIFO_ISEMPTY( *p_fifo ) )
+            {
+                vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+                if( p_fifo->b_die )
+                {
+                    vlc_mutex_unlock( &p_fifo->data_lock );
+                    p_bit_stream->p_byte = p_zero;
+                    p_bit_stream->p_end = &p_zero[sizeof(p_zero) - 1];
+                    return;
+                }
+            }
+
+            /* The next byte could be found in the next PES packet */
+            p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first;
+
+            /* We can release the fifo's data lock */
+            vlc_mutex_unlock( &p_fifo->data_lock );
+        }
+        else
+        {
+            /* Perhaps the next data packet of the current PES packet contains
+             * real data (ie its payload's size is greater than 0). */
+            p_bit_stream->p_data = p_bit_stream->p_data->p_next;
+        }
+    } while ( p_bit_stream->p_data->p_payload_start
+               == p_bit_stream->p_data->p_payload_end );
+
+    /* We've found a data packet which contains interesting data... */
+    p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
+    p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
+
+    /* Copy remaining bits of the previous packet */
+    *((WORD_TYPE *)p_bit_stream->p_byte - 1) = buffer_left;
+    p_bit_stream->p_byte -= i_bytes_left;
+}
diff --git a/src/input/input_file.c b/src/input/input_file.c
deleted file mode 100644 (file)
index 1e8994e..0000000
+++ /dev/null
@@ -1,1127 +0,0 @@
-/*****************************************************************************
- * input_file.c: functions to read from a file
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
- *          Samuel Hocevar <sam@via.ecp.fr>
- *
- * 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 <stdio.h>
-#include <unistd.h>                                               /* close() */
-#include <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
-#include <sys/stat.h>                                    /* fstat, off_t ... */
-#include <netinet/in.h>                                           /* ntohl() */
-#include <fcntl.h>                                                 /* open() */
-#include <malloc.h>                                      /* malloc, read ... */
-#include <string.h>
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "plugins.h"
-#include "playlist.h"
-#include "intf_msg.h"
-
-#include "main.h"
-
-#include "input.h"
-#include "input_ps.h"
-#include "input_file.h"
-
-#define BUF_SIZE (797*3)
-
-#define PS_METHOD 1
-#define TS_METHOD 2
-
-#define TS_PACKET_SIZE 188
-#define TS_IN_UDP 7
-
-#define MAX_AUDIO_CHANNEL 15
-#define MAX_SUBTITLES_CHANNEL 31
-#define NO_SUBTITLES 255
-
-#define PS_BUFFER_SIZE 16384
-
-#define NO_PES          0x00
-#define AUDIO_PES       0x01
-#define VIDEO_PES       0x02
-#define AC3_PES         0x03
-#define SUBTITLE_PES    0x04
-#define LPCM_PES        0x05
-#define PRIVATE_PES     0x06
-#define UNKNOWN_PES     0x12
-
-#define PCR_PID 0x20 /* 0x20 == first video stream
-                      * 0x40 == first audio stream */
-
-typedef u8 file_ts_packet[TS_PACKET_SIZE];
-typedef file_ts_packet udp_packet[TS_IN_UDP];
-
-typedef struct synchro_struct
-{
-    mtime_t     delta_clock;
-    mtime_t     slope;
-    mtime_t     last_pcr_time;
-    
-    file_ts_packet *last_pcr;
-} synchro_t;
-
-typedef struct in_data_s
-{
-    int start, end;
-    vlc_mutex_t lock;
-    vlc_cond_t notfull;
-    vlc_cond_t notempty;
-    udp_packet buf[BUF_SIZE+1];
-} in_data_t;
-
-typedef struct own_pcr_s
-{
-    int start, end;
-    vlc_mutex_t lock;
-    file_ts_packet *buf[(BUF_SIZE+1)*TS_IN_UDP+1];
-} own_pcr_t;
-
-typedef struct options_s
-{
-    unsigned int pcr_pid;
-    u8 i_file_type;
-    int in; 
-} options_t;
-
-typedef struct s_ps
-{
-    unsigned int pat_counter;
-    unsigned int pmt_counter;
-
-    /*
-     * These 3 parameters are passed 
-     * as command line arguments
-     */
-    unsigned int audio_channel;
-    unsigned int subtitles_channel;
-    unsigned int audio_type;
-
-    /* 
-     * 16 audio mpeg streams
-     * 16 audio AV3 streams
-     * 16 video mpeg streams
-     * 32 subtitle streams
-     */
-    unsigned int media_counter[0x100];
-    unsigned int association_table[0x100];
-    unsigned int found_streams;
-
-    unsigned int found_pts;
-
-    unsigned int ts_to_write;
-    unsigned int ts_written;
-    unsigned int sent_ts;
-
-    unsigned char *ps_data;
-    unsigned char *ps_end;
-    unsigned char *ps_buffer;
-
-    unsigned int pes_id;
-    unsigned int private_id;
-    unsigned int has_pts;
-    unsigned int pcr_pid;
-
-    unsigned int pes_type;
-    unsigned int pes_size;
-    unsigned int to_skip;
-    unsigned int offset;
-} ps_t;
-
-typedef struct input_file_s
-{
-    boolean_t    b_die; /* b_die flag for the disk thread */
-    vlc_thread_t disk_thread;
-
-    synchro_t    synchro;
-    ps_t         ps;
-    in_data_t    in_data;
-    options_t    options;
-    own_pcr_t    own_pcr;
-} input_file_t;
-
-/* local prototypes */
-void ps_fill( input_file_t * p_if, boolean_t wait );
-ssize_t safe_read(options_t *p_options, unsigned char *buf, int count);
-void input_DiskThread( input_file_t * p_if );
-int init_synchro( input_file_t * p_if );
-
-input_file_t input_file;
-
-/******************************************************************************
- * ConvertPCRTime : extracts and converts the PCR time in microseconds
- ******************************************************************************/
-
-s64 ConvertPCRTime(file_ts_packet *pcr_buff)
-{
-    return( (((((s64)U32_AT(((u8*)pcr_buff)+6)) << 1) | (((u8*)pcr_buff)[10] >> 7)) * 300) / 27 );
-}
-
-/******************************************************************************
- * wait_a_moment : Compute how long we must wait before sending a TS packet
- ******************************************************************************/
-
-static void wait_a_moment( input_file_t * p_if, file_ts_packet *ts)
-{
-    synchro_t * p_synchro = &input_file.synchro;
-    
-    static int retard_count = 0;
-    static s64 wait_max = 0;
-    s64 sendtime; /* the date at which the TS packet should be sent */
-    s64 wait;
-    
-    sendtime = p_synchro->last_pcr_time + p_synchro->delta_clock +
-        p_synchro->slope * ((ts - p_synchro->last_pcr + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP)); 
-    wait = sendtime - mdate();
-    if( wait > 0 )
-    { 
-        retard_count = 0;
-        if(wait > 100000)
-        {
-            intf_DbgMsg( "input warning: wait time may be too long : %Ld\n", wait );
-            return;
-        }
-        msleep( wait );
-    }
-    else
-    {
-        if( wait < wait_max )
-        {
-            wait_max = wait;
-        }
-        retard_count++;
-        if( retard_count == 16 )
-        {
-            retard_count = 0;
-        }
-    }
-}
-
-/******************************************************************************
- * adjust : Adjust the encoder clock & remove the PCR from own_pcr
- ******************************************************************************/
-
-static void adjust( input_file_t * p_if, file_ts_packet *ts )
-{
-    synchro_t * p_synchro = &p_if->synchro;
-    own_pcr_t * p_own_pcr = &p_if->own_pcr;
-    file_ts_packet *next_pcr;
-    int no_discontinuity = 1;
-    
-    if( ((u8*)ts)[5] & 0x80 )
-    {
-        /* There is a discontinuity - I recalculate the delta */
-        p_synchro->delta_clock = mdate() - ConvertPCRTime(ts);
-        intf_DbgMsg( "input warning: clock discontinuity\n" );
-        no_discontinuity = 0;
-    }
-    else
-    {
-        p_synchro->last_pcr = ts;
-        p_synchro->last_pcr_time = ConvertPCRTime( ts );
-    }
-        
-    vlc_mutex_lock(&p_own_pcr->lock);
-    p_own_pcr->start++;
-    p_own_pcr->start %= (BUF_SIZE+1)*TS_IN_UDP+1;
-    
-    /* If we have 2 consecutiv PCR, we can reevaluate slope */
-    if( (p_own_pcr->start != p_own_pcr->end) &&
-        no_discontinuity &&
-        !((((u8*) next_pcr = p_own_pcr->buf[p_own_pcr->start]))[5] & 0x80))
-    {
-        s64 current_pcr_time = ConvertPCRTime(ts);
-        s64 next_pcr_time =    ConvertPCRTime(next_pcr);
-        
-        if( (next_pcr_time - current_pcr_time < 0) || (next_pcr_time - current_pcr_time > 700000))
-        {
-            intf_DbgMsg( "input warning: possible discontinuity\n" );
-            p_synchro->delta_clock = mdate() - next_pcr_time;
-        }
-        else
-        {
-            p_synchro->slope = (next_pcr_time - current_pcr_time) /
-                ((next_pcr - ts + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP));
-        }
-    }
-    
-    vlc_mutex_unlock(&p_own_pcr->lock);
-}
-
-/*****************************************************************************
- * file_next : Opens the next available file
- *****************************************************************************/
-
-int file_next( options_t *options )
-{
-    p_playlist_t p_playlist = p_main->p_playlist;
-
-    /* the check for index == 0 has to be done _before_ */
-    p_playlist->i_index--;
-
-    /* close the file we just finished */
-    if( options->in != -1 )
-    {
-        close( options->in );
-    }
-
-    /* open the next file */
-    if( !strcmp( p_playlist->p_list[ p_playlist->i_index ], "-" ) )
-    {
-        /* read stdin */
-        return ( options->in = 0 );
-    }
-    else
-    {
-        /* read the actual file */
-        intf_Msg( "Playing file %s\n",
-                  p_playlist->p_list[ p_playlist->i_index ] );
-
-        options->in =
-            open( p_playlist->p_list[ p_playlist->i_index ],
-                  O_RDONLY | O_NONBLOCK );
-
-        return ( options->in );
-    }
-}
-
-/*****************************************************************************
- * safe_read : Buffered reading method
- *****************************************************************************/
-
-ssize_t safe_read( options_t *options, unsigned char *buf, int count )
-{
-    int ret, cnt=0;
-    
-    while( cnt < count )
-    {
-        ret = read( options->in, buf + cnt, count - cnt );
-    
-        if( ret < 0 )
-            return ret;
-    
-        if( ret == 0 )
-        {
-            /* zero means end of file */
-            if( p_main->p_playlist->i_index )
-            {
-                file_next( options );
-            }
-            else
-            {
-                break;
-            }
-        }
-    
-        cnt += ret;
-    }
-
-    return cnt;
-}
-
-/******************************************************************************
- * keep_pcr : Put a TS packet in the fifo if it owns a PCR
- ******************************************************************************/
-
-int keep_pcr(int pcr_pid, file_ts_packet *ts)
-{
-    own_pcr_t * p_own_pcr =   &input_file.own_pcr;
-
-#define p ((u8 *)ts)
-    if ((p[3] & 0x20) && p[4] && (p[5] & 0x10)
-        && ((((p[1]<<8)+p[2]) & 0x1FFF) == pcr_pid))
-    {
-        /* adaptation_field_control is set, adaptation_field_lenght is not 0,
-         * PCR_flag is set, pid == pcr_pid */
-        vlc_mutex_lock(&p_own_pcr->lock);
-        p_own_pcr->buf[p_own_pcr->end++] = ts;
-        p_own_pcr->end %= (BUF_SIZE+1)*TS_IN_UDP+1;
-        vlc_mutex_unlock(&p_own_pcr->lock);
-        return 1;
-    } 
-    else
-        return 0;
-#undef p
-}
-
-/******************************************************************************
- * get_pid : gets a pid from a PES type
- ******************************************************************************/
-
-int get_pid (ps_t *p_ps)
-{
-    int i, tofind, delta;
-    char* type;
-
-    switch( p_ps->pes_type )
-    {
-        case VIDEO_PES:
-            delta = 0x20; /* 0x20 - 0x2f */
-            type = "MPEG video";
-            tofind = p_ps->pes_id;
-            break;
-        case AUDIO_PES:
-            delta = 0x40; /* 0x40 - 0x5f */
-            type = "MPEG audio";
-            tofind = p_ps->pes_id;
-            break;
-        /* XXX: 0x64 is for the PMT, so don't take it !!! */
-        case AC3_PES:
-            delta = 0x80; /* 0x80 - 0x8f */
-            type = "MPEG private (AC3 audio)";
-            tofind = p_ps->private_id;
-            break;
-        case LPCM_PES:
-            delta = 0x90; /* 0x90 - 0x9f */
-            type = "MPEG private (LPCM audio)";
-            tofind = p_ps->private_id;
-            break;
-        case SUBTITLE_PES:
-            delta = 0xa0; /* 0xa0 - 0xbf */
-            type = "MPEG private (DVD subtitle)";
-            tofind = p_ps->private_id;
-            break;
-        default:
-            return(-1);
-
-    }
-
-    i = delta + (tofind & 0x1f);
-
-    if( p_ps->association_table[i] == 0)
-    {
-        intf_Msg( "Found %s stream at 0x%.2x, allocating PID 0x%.2x\n",
-                  type, tofind, i );
-        p_ps->association_table[i] = 1;
-    }
-
-    return ( i );
-
-}
-
-/******************************************************************************
- * write_media_ts : writes a ts packet from a ps stream
- ******************************************************************************/
-
-void write_media_ts(ps_t *ps, unsigned char *ts, unsigned int pid)
-{
-    int i,j;
-    s64 clock;
-    long int extclock;
-
-    /* if offset == 0, it means we haven't examined the PS yet */
-    if (ps->offset == 0)
-    {
-        if (ps->pes_size < 184) {
-
-            ts[0] = 0x47;    /* sync_byte */
-            ts[1] = 0x40;    /* payload_unit_start_indicator si début de PES */
-            ts[2] = pid;
-
-            ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
-            ts[4] = 184 - ps->pes_size - 1;
-            ts[5] = 0x00;
-            for (i=6 ; i < 188 - ps->pes_size ; i++) ts[i]=0xFF; /* facultatif ? */
-            memcpy(ts + 188 - ps->pes_size, ps->ps_data, ps->pes_size);
-            
-            /* this PS is finished, next time we'll pick a new one */
-            ps->pes_type = NO_PES;
-            ps->ps_data += ps->pes_size;
-            ps->offset += ps->pes_size;
-            return;
-
-        }
-    }
-
-    /* now we still can have offset == 0, but size is initialized */
-    
-    ts[0] = 0x47;                /* sync_byte */
-    ts[1] = (ps->offset == 0) ? 0x40 : 0x00;    /* payload_unit_start_indicator si début de PES */
-    ts[2] = pid;
-
-    if ( (ps->offset == 0) && (ps->has_pts == 0xc0) && (ps->pcr_pid == pid) )
-    {
-
-        ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
-        ts[4] = 0x07;            /* taille de l'adaptation field */
-        ts[5] = 0x50;            /* rtfm */
-        
-        /* on va lire le PTS */
-        clock = ( ((s64)(ps->ps_data[9] & 0x0E) << 29) |
-            (((s64)U16_AT(ps->ps_data + 10) << 14) - (1 << 14)) |
-            ((s64)U16_AT(ps->ps_data + 12) >> 1) );
-        
-        ps->has_pts = 0;
-
-        extclock = 0x000;
-        ts[6] = (clock & 0x1fe000000) >> 25;    /* ---111111110000000000000000000000000 */
-        ts[7] = (clock & 0x001fe0000) >> 17;    /* ---000000001111111100000000000000000 */
-        ts[8] = (clock & 0x00001fe00) >>  9;    /* ---000000000000000011111111000000000 */
-        ts[9] = (clock & 0x0000001fe) >>  1;    /* ---000000000000000000000000111111110 */
-            
-        ts[10] = 0x7e + ((clock & 0x01) << 7) + ((extclock & 0x100) >> 8);
-        ts[11] = extclock & 0xff;
-    
-        memcpy(ts + 4 + 8, ps->ps_data, 184 - 8);
-            
-        ts[15] = 0xe0; /* FIXME : we don't know how to choose program yet */
-         
-        ps->offset += 184 - 8;
-        ps->ps_data += 184 - 8;
-    }
-    else if (ps->offset <= ps->pes_size - 184)
-    {
-            
-        ts[3] = 0x10 + (ps->media_counter[pid] & 0x0f);
-        memcpy(ts + 4, ps->ps_data, 184);
-
-        ps->offset += 184;
-        ps->ps_data += 184;
-   
-    }
-    else
-    {
-            
-        j = ps->pes_size - ps->offset;
-        ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
-        ts[4] = 184 - j - 1;
-        ts[5] = 0x00;
-        for (i=6 ; i < 188 - j ; i++) ts[i]=0xFF; /* facultatif ? */
-        memcpy(ts + 4 + 184 - j, ps->ps_data, j);
-        ps->offset += j; /* offset = size */
-        ps->ps_data += j; /* offset = size */
-
-        /* the PES is finished */
-        ps->pes_type = NO_PES;
-        ps->sent_ts++;
-
-    }
-
-}
-
-/******************************************************************************
- * write_pat : writes a program association table
- ******************************************************************************/
-
-void write_pat(ps_t *ps, unsigned char *ts)
-{
-    int i;
-
-    ts[0] = 0x47;        /* sync_byte */
-    ts[1] = 0x40;
-    ts[2] = 0x00;        /* PID = 0x0000 */
-    ts[3] = 0x10 + (ps->pat_counter & 0x0f);
-    ts[4] = ts[5] = 0x00;
-    
-    ts[6] = 0xb0; /* */
-    ts[7] = 0x11; /* section_length = 0x011 */
-
-    ts[8] = 0x00;
-    ts[9] = 0xb0; /* TS id = 0x00b0 */
-
-    ts[10] = 0xc1;
-    /* section # and last section # */
-    ts[11] = ts[12] = 0x00;
-
-    /* Network PID (useless) */
-    ts[13] = ts[14] = 0x00; ts[15] = 0xe0; ts[16] = 0x10;
-
-    /* Program Map PID */
-    ts[17] = 0x03; ts[18] = 0xe8; ts[19] = 0xe0; ts[20] = 0x64;
-
-    /* CRC */
-    ts[21] = 0x4d; ts[22] = 0x6a; ts[23] = 0x8b; ts[24] = 0x0f;
-
-    for (i=25 ; i < 188 ; i++) ts[i]=0xFF; /* facultatif ? */
-
-    ps->sent_ts++;
-}
-
-/******************************************************************************
- * write_pmt : writes a program map table
- ******************************************************************************/
-
-void write_pmt(ps_t *ps, unsigned char *ts)
-{
-    int i;
-    
-    ts[0] = 0x47;        /* sync_byte */
-    ts[1] = 0x40;
-    ts[2] = 0x0064;        /* PID = 0x0064 */
-    ts[3] = 0x10 + (ps->pmt_counter & 0x0f);
-    
-    ts[4] = 0x00;
-    ts[5] = 0x02;
-    
-    ts[6] = 0xb0; /* */
-    ts[7] = 0x34; /* section_length = 0x034 */
-
-    ts[8] = 0x03;
-    ts[9] = 0xe8; /* prog number */
-
-    ts[10] = 0xc1;
-    /* section # and last section # */
-    ts[11] = ts[12] = 0x00;
-
-    /* PCR PID */
-    ts[13] = 0xe0;
-    ts[14] = 0x20;
-
-    /* program_info_length == 0 */
-    ts[15] = 0xf0; ts[16] = 0x00;
-
-    /* Program Map / Video PID */
-    ts[17] = 0x02; /* stream type = video */
-    ts[18] = 0xe0; ts[19] = 0x20;
-    ts[20] = 0xf0; ts[21] = 0x09; /* es info length */
-
-    /* useless info */
-    ts[22] = 0x07; ts[23] = 0x04; ts[24] = 0x08; ts[25] = 0x80; ts[26] = 0x24;
-    ts[27] = 0x02; ts[28] = 0x11; ts[29] = 0x01; ts[30] = 0xfe;
-
-    switch ( ps->audio_type )
-    {
-    case 12 :
-    case REQUESTED_AC3 :
-        /* ac3 */
-        ts[31] = 0x81; /* stream type = audio */
-        ts[32] = 0xe0; ts[33] = 0x80 + ps->audio_channel;
-        ts[34] = 0xf0; ts[35] = 0x00; /* es info length */
-        break;
-
-    case REQUESTED_MPEG :
-        /* mpeg */
-        ts[31] = 0x04; /* stream type = audio */
-        ts[32] = 0xe0; ts[33] = 0x40 + ps->audio_channel;
-        ts[34] = 0xf0; ts[35] = 0x00; /* es info length */
-        break;
-
-    case REQUESTED_LPCM :
-        /* LPCM audio */
-        ts[31] = 0x81;
-        ts[32] = 0xe0; ts[33] = 0xa0 + ps->audio_channel;
-        ts[34] = 0xf0; ts[35] = 0x00; /* es info  length */
-        break;
-
-    default :
-        /* No audio */
-        ts[31] = 0x00;
-        ts[35] = 0x00; /* es info  length */
-    }
-
-    /* Subtitles */
-    if( ps->subtitles_channel == NO_SUBTITLES )
-    {
-        ts[36] = 0x00;
-        ts[37] = 0x00; ts[38] = 0x00;
-        ts[39] = 0xf0; ts[40] = 0x00; /* es info length */
-    }
-    else
-    {
-        ts[36] = 0x82;
-        ts[37] = 0xe0; ts[38] = 0xa0 + ( ps->subtitles_channel );
-        ts[39] = 0xf0; ts[40] = 0x00; /* es info length */
-    }
-
-    /* CRC FIXME: not calculated yet*/
-    ts[41] = 0x96; ts[42] = 0x70; ts[43] = 0x0b; ts[44] = 0x7c;
-
-    /* stuffing bytes */
-    for (i=45 ; i < 188 ; i++) ts[i]=0xff; /* facultatif ? */
-
-    ps->sent_ts++;
-}
-
-
-/******************************************************************************
- * ps_thread
- ******************************************************************************
- * We use threading to allow cool non-blocking read from the disk. This
- * implicit thread is the disk (producer) thread, it reads packets from
- * the PS file on the disk, and stores them in a FIFO.
- ******************************************************************************/
-
-void ps_thread( input_file_t * p_if )
-{
-    int i;
-    ps_t * p_ps =             &p_if->ps;
-    own_pcr_t * p_own_pcr =   &p_if->own_pcr;
-    in_data_t * p_in_data =   &p_if->in_data;
-    /* Initialize the structures */
-    p_own_pcr->start = p_own_pcr->end = 0; /* empty FIFO */
-    vlc_mutex_init( &p_own_pcr->lock );
-    p_in_data->start = p_in_data->end = 0; /* empty FIFO */
-    vlc_mutex_init( &p_in_data->lock );
-    vlc_cond_init( &p_in_data->notfull );
-    vlc_cond_init( &p_in_data->notempty );
-    
-    p_ps->audio_type = main_GetIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_AC3 );
-    p_ps->audio_channel = main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 );
-    p_ps->subtitles_channel = main_GetIntVariable( INPUT_DVD_SUBTITLE_VAR, 0 );
-
-    p_ps->pes_type = NO_PES;
-    p_ps->pes_id = 0;
-    p_ps->private_id = 0;
-    p_ps->pes_size = 0;
-    p_ps->to_skip = 0;
-    p_ps->pmt_counter = 0;
-    p_ps->pat_counter = 0;
-    for( i=0; i<256; i++ )
-        p_ps->association_table[i] = 0;
-    p_ps->offset = 0;
-    p_ps->found_pts = 0;
-    p_ps->found_streams = 0;
-    p_ps->pcr_pid = p_if->options.pcr_pid;
-
-    p_ps->ps_buffer = malloc(PS_BUFFER_SIZE);
-    /* those 2 addresses are initialized so that a new packet is read */
-    p_ps->ps_data = p_ps->ps_buffer + PS_BUFFER_SIZE - 1;
-    /* fix the first byte stuff */
-    p_ps->ps_data[0] = 0x00;
-    p_ps->ps_end = p_ps->ps_buffer + PS_BUFFER_SIZE;
-    
-    /* Fill the fifo until it is full */
-    ps_fill( p_if, 0 );
-    /* Launch the thread which fills the fifo */
-    vlc_thread_create( &p_if->disk_thread, "disk thread",
-                       (vlc_thread_func_t)input_DiskThread, p_if ); 
-    /* Init the synchronization XXX add error detection !!! */
-    init_synchro( p_if );
-}
-
-/******************************************************************************
- * ps_read : ps reading method
- ******************************************************************************/
-
-ssize_t ps_read( options_t *p_options, ps_t * p_ps, void *ts )
-{
-    int pid, readbytes = 0;
-    int datasize;
-    p_ps->ts_written = 0;
-  
-    while(p_ps->ts_to_write)
-    {   
-
-        /* if there's not enough data to send */
-        if((datasize = p_ps->ps_end - p_ps->ps_data) <= TS_PACKET_SIZE)
-        {
-            /* copy the remaining bits at the beginning of the PS buffer */
-            memmove ( p_ps->ps_buffer, p_ps->ps_data, datasize);
-            /* read some bytes */
-            readbytes = safe_read( p_options, p_ps->ps_buffer + datasize, PS_BUFFER_SIZE - datasize);
-
-            if(readbytes <= 0)
-            {
-                input_file.b_die = 1;
-                return -1;
-            }
-            p_ps->ps_data = p_ps->ps_buffer;
-            p_ps->ps_end = p_ps->ps_data + datasize + readbytes;
-        }
-
-        //printf("offset is %x, pes total size is %x, to skip is %x\n", p_ps->offset, p_ps->pes_size, p_ps->to_skip );
-        if( p_ps->to_skip == 0 && p_ps->offset == p_ps->pes_size )
-        {
-            if( p_ps->ps_data[0] || p_ps->ps_data[1] || (p_ps->ps_data[2] != 0x01) )
-            {
-                intf_ErrMsg ( "input error: not a startcode (0x%.2x%.2x%.2x instead of 0x000001)\n", p_ps->ps_data[0], p_ps->ps_data[1], p_ps->ps_data[2] );
-                return -1;
-            }
-
-            p_ps->pes_type = NO_PES;
-            p_ps->offset = 0;
-            p_ps->pes_size = (p_ps->ps_data[4] << 8) + p_ps->ps_data[5] + 6;
-            p_ps->has_pts = p_ps->ps_data[7] & 0xc0;
-        }
-
-        /* if the actual data we have in pes_data is not a PES, then
-         * we read the next one. */
-        if( (p_ps->pes_type == NO_PES) && !p_ps->to_skip )
-        {
-            p_ps->pes_id = p_ps->ps_data[3];
-
-            if (p_ps->pes_id == 0xbd)
-            {
-                p_ps->private_id = p_ps->ps_data[ 9 + p_ps->ps_data[8] ];
-                if ((p_ps->private_id & 0xf0) == 0x80)
-                {
-                    /* flux audio ac3 */
-                    p_ps->pes_type = AC3_PES;
-                }
-                else if ((p_ps->private_id & 0xf0) == 0x20)
-                {
-                    /* subtitles */
-                    p_ps->pes_type = SUBTITLE_PES;
-                }
-                else
-                {
-                    /* unknown private data */
-                    p_ps->pes_type = PRIVATE_PES;
-                }
-            }
-            else if ((p_ps->pes_id & 0xe0) == 0xc0)
-            {
-                /* flux audio */
-                p_ps->pes_type = AUDIO_PES;
-               //write (1, p_ps->ps_data + 9 + p_ps->ps_data[8], 2048 - (9 + p_ps->ps_data[8]));
-            }
-            else if ((p_ps->pes_id & 0xf0) == 0xe0)
-            {
-                /* flux video */
-                p_ps->pes_type = VIDEO_PES;
-            }
-            else if (p_ps->pes_id == 0xba)
-            {
-                p_ps->pes_type = NO_PES;
-                p_ps->pes_size = 14; /* 8 extra characters after 0x000001ba**** */
-                p_ps->to_skip = 14;
-            }
-            else
-            {
-                p_ps->pes_type = UNKNOWN_PES;
-                p_ps->to_skip = p_ps->pes_size;
-            }
-        }
-
-        if( p_ps->to_skip )
-        {
-            if( p_ps->to_skip < TS_PACKET_SIZE )
-            {
-                p_ps->ps_data += p_ps->to_skip;
-                p_ps->offset += p_ps->to_skip;
-                p_ps->to_skip = 0;
-            }
-            else
-            {
-                p_ps->ps_data += TS_PACKET_SIZE;
-                p_ps->offset += TS_PACKET_SIZE;
-                p_ps->to_skip -= TS_PACKET_SIZE;
-            }
-        }
-
-        /* now that we know what we have, we can either 
-         * write this packet's data in the buffer, skip it,
-         * or write a PMT or PAT table and wait for the next
-         * turn before writing the packet. */
-        switch (p_ps->sent_ts & 0xff)
-        {
-            case 0x80:
-                write_pmt(p_ps,ts);
-                p_ps->pmt_counter++;
-                p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
-                break;
-            case 0x00:
-                write_pat(p_ps,ts);
-                p_ps->pat_counter++;
-                p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
-                break;
-        }
-
-        /* if there's still no found PCR_PID, and no PTS in this PES, we trash it */
-        if (!p_ps->found_pts)
-        {
-            if (p_ps->has_pts)
-            {
-                intf_Msg( "input: found a PTS, at last ...\n" );
-                p_ps->found_pts = 1;
-            }
-            else
-                p_ps->pes_type = NO_PES;
-        }
-
-        if (p_ps->ts_to_write)
-        {
-            switch(p_ps->pes_type)
-            {
-                case VIDEO_PES:
-                case AUDIO_PES:
-                case SUBTITLE_PES:
-                case AC3_PES:
-                    pid = get_pid (p_ps);
-                    write_media_ts(p_ps, ts, pid);
-                    p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
-                    p_ps->media_counter[pid]++;
-                    break;
-                case UNKNOWN_PES:
-                default:
-                    p_ps->pes_type = NO_PES;
-                    break;
-            }
-        }
-    }
-
-    //p_ps->ps_data += TS_PACKET_SIZE;
-
-    return p_ps->ts_written;
-}
-
-/******************************************************************************
- * ps_fill : Fill the data buffer with TS created from a PS file
- ******************************************************************************/
-
-void ps_fill( input_file_t * p_if, boolean_t wait )
-{
-    in_data_t * p_in_data = &p_if->in_data;
-    ps_t * p_ps = &p_if->ps;
-    int i, howmany;
-    int pcr_flag;
-    file_ts_packet *ts;
-
-    /* How many TS packet for the next UDP packet */
-    howmany = TS_IN_UDP;
-
-    pcr_flag = 0;
-    /* for every single TS packet */
-    while( !p_if->b_die )
-    {        
-        /* wait until we have one free item to store the UDP packet read */
-        vlc_mutex_lock(&p_in_data->lock);
-        while((p_in_data->end+BUF_SIZE+1-p_in_data->start)%(BUF_SIZE+1) == BUF_SIZE )
-        {
-            /* The buffer is full */
-            if(wait)
-            {
-                vlc_cond_wait(&p_in_data->notfull, &p_in_data->lock);
-                if( p_if->b_die )
-                    return;
-            }
-            else
-            {
-                vlc_mutex_unlock(&p_in_data->lock);
-                if (!pcr_flag)
-                {
-                    intf_ErrMsg( "input error: bad PCR PID\n" );
-                }
-                return;
-            }
-        }
-        vlc_mutex_unlock(&p_in_data->lock);
-        
-        /* read a whole UDP packet from the file */
-        p_ps->ts_to_write = howmany;
-        if( ps_read( &p_if->options, p_ps, ts = (file_ts_packet *)(p_in_data->buf + p_in_data->end) ) != howmany )
-        {
-            msleep( 50000 ); /* XXX we need an INPUT_IDLE */
-            return;
-        }
-        
-        /* Scan to mark TS packets containing a PCR */
-        for( i = 0 ; i < howmany ; i++ , ts++ )
-        {
-            pcr_flag |= keep_pcr( p_ps->pcr_pid, ts );
-        }
-        
-        vlc_mutex_lock( &p_in_data->lock );
-        p_in_data->end++;
-        p_in_data->end %= BUF_SIZE + 1;
-        vlc_cond_signal( &p_in_data->notempty );
-        vlc_mutex_unlock( &p_in_data->lock );
-    }
-}
-
-int init_synchro( input_file_t * p_if )
-{
-    int i, pcr_count;
-    int howmany = TS_IN_UDP;
-    file_ts_packet * ts;
-    synchro_t * p_synchro = &p_if->synchro;
-    in_data_t * p_in_data = &p_if->in_data;
-    own_pcr_t * p_own_pcr = &p_if->own_pcr; 
-    
-    p_synchro->slope = 0;
-    pcr_count = 0;
-    
-    /*
-     * Initialisation of the synchro mecanism : wait for 1 PCR
-     * to evaluate delta_clock
-     */
-
-    while( 1 )
-    {
-        vlc_mutex_lock( &p_in_data->lock );
-        
-        while( p_in_data->end == p_in_data->start )
-        {
-            vlc_cond_wait(&p_in_data->notempty, &p_in_data->lock);
-        }
-
-        vlc_mutex_unlock( &p_in_data->lock );
-        
-        ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
-        for( i=0 ; i < howmany ; i++, ts++ )
-        {
-            if( ts == p_own_pcr->buf[p_own_pcr->start] && !(((u8*)ts)[5] & 0x80) )
-            {
-                p_synchro->last_pcr = ts;
-                p_synchro->last_pcr_time = ConvertPCRTime( ts );
-                p_synchro->delta_clock = mdate() - ConvertPCRTime(ts);
-                adjust( p_if, ts );
-                pcr_count++;
-            }
-        }
-        
-        vlc_mutex_lock( &p_in_data->lock );
-        p_in_data->start++;
-        p_in_data->start %= BUF_SIZE + 1;
-        vlc_cond_signal( &p_in_data->notfull );
-        vlc_mutex_unlock( &p_in_data->lock );
-        
-        if(pcr_count)
-            break; 
-    }
-    return( 0 );
-}
-
-/*****************************************************************************
- * input_DiskThread : main thread
- *****************************************************************************/
-
-void input_DiskThread( input_file_t * p_if )
-{
-    ps_fill( p_if, 1 );    
-    vlc_thread_exit();
-}
-
-/*****************************************************************************
- * input_FileOpen : open a file descriptor
- *****************************************************************************/
-int input_FileOpen( input_thread_t *p_input )
-{
-    options_t * p_options = &input_file.options;
-
-    p_options->in = -1;
-
-    if( file_next( p_options ) < 0 )
-    {
-        intf_ErrMsg( "input error: cannot open the file %s\n",
-                     p_input->p_source );
-        return( 1 );
-    }
-
-    input_file.b_die = 0;
-    if( safe_read( p_options, &p_options->i_file_type, 1 ) <= 0 )
-    {
-        intf_ErrMsg( "input error: cannot read file type\n");
-        close( p_options->in );
-        return( 1 );
-    }
-    
-    switch( p_options->i_file_type )
-    {
-    case 0x00:
-        p_options->pcr_pid = PCR_PID;
-        ps_thread( &input_file );
-        break;
-    case 0x47:
-        intf_ErrMsg( "input error: ts files are not currently supported\n" );
-        close( p_options->in );
-        return( 1 );
-    default:
-        intf_ErrMsg( "input error: cannot determine stream type\n" );
-        close( p_options->in );
-        return( 1 );
-    }
-
-    return( 0 );
-}
-
-/*****************************************************************************
- * input_FileRead : read from a file
- *****************************************************************************/
-int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
-                    size_t i_count )
-{
-    in_data_t * p_in_data = &input_file.in_data;
-    synchro_t * p_synchro = &input_file.synchro;
-    own_pcr_t * p_own_pcr = &input_file.own_pcr;
-    int i, howmany;
-    file_ts_packet * ts;
-    
-    /* XXX XXX XXX
-     * End condition not verified, should put a flag in ps_fill
-     */
-    howmany = TS_IN_UDP;
-
-    vlc_mutex_lock( &p_in_data->lock );
-    while( p_in_data->end == p_in_data->start )
-    {
-        if( input_file.b_die )
-        {
-            vlc_mutex_unlock( &p_in_data->lock );
-            /* wait 1 second, like the network input */
-            msleep( 1000000 );
-            return( 0 );
-        }
-
-        vlc_cond_wait( &p_in_data->notempty, &p_in_data->lock );
-    }
-    vlc_mutex_unlock( &p_in_data->lock );
-
-    ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
-    for( i=0 ; i < howmany ; i++, ts++ )
-    {             
-        if( p_synchro->slope && (i == howmany-1) )
-        {
-            wait_a_moment( &input_file, ts );
-        }
-        if( ts  == p_own_pcr->buf[p_own_pcr->start] )
-        {
-            /* the TS packet contains a PCR, so we try to adjust the clock */
-            adjust( &input_file, ts );
-        }
-    }
-
-    for( i=0 ; i<howmany ; i++ )
-    {
-        memcpy( p_vector[i].iov_base, (char*)(ts - howmany + i), p_vector[i].iov_len );
-    }
-
-    vlc_mutex_lock(&p_in_data->lock);
-    p_in_data->start++;
-    p_in_data->start %= BUF_SIZE + 1;
-    vlc_cond_signal(&p_in_data->notfull);
-    vlc_mutex_unlock(&p_in_data->lock);
-    
-    return( 188 * howmany );
-}
-
-/*****************************************************************************
- * input_FileClose : close a file descriptor
- *****************************************************************************/
-void input_FileClose( input_thread_t *p_input )
-{
-    input_file.b_die = 1;
-    vlc_cond_signal( &input_file.in_data.notfull );
-    vlc_thread_join( input_file.disk_thread );
-
-    close( input_file.options.in );
-}
-
diff --git a/src/input/input_file.h b/src/input/input_file.h
deleted file mode 100644 (file)
index 9abc9a9..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * input_file.h: file streams functions interface
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int     input_FileOpen  ( input_thread_t *p_input );
-int     input_FileRead  ( input_thread_t *p_input, const struct iovec *p_vector,
-                          size_t i_count );
-void    input_FileClose ( input_thread_t *p_input );
diff --git a/src/input/input_netlist.c b/src/input/input_netlist.c
deleted file mode 100644 (file)
index 5b40c56..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*****************************************************************************
- * netlist.c: input thread
- * Manages the TS and PES netlists (see netlist.h).
- *****************************************************************************
- * Copyright (C) 1998, 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * 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 <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
-
-#include <stdlib.h>                                                /* free() */
-#include <string.h>                                            /* strerror() */
-#include <errno.h>                                                  /* errno */
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "intf_msg.h"
-#include "debug.h"
-#include "input.h"
-#include "input_netlist.h"
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-
-/*****************************************************************************
- * input_NetlistOpen: initialize the netlists buffers
- *****************************************************************************/
-int input_NetlistInit( input_thread_t *p_input )
-{
-    int                 i_base, i_packets, i_iovec;
-
-    /* Initialize running indexes. */
-#ifdef INPUT_LIFO_TS_NETLIST
-    p_input->netlist.i_ts_index = INPUT_TS_READ_ONCE;
-#else
-    p_input->netlist.i_ts_start = 0;
-    p_input->netlist.i_ts_end = 0;
-#endif
-#ifdef INPUT_LIFO_PES_NETLIST
-    p_input->netlist.i_pes_index = 1; /* We allocate one PES at a time */
-#else
-    p_input->netlist.i_pes_start = 0;
-    p_input->netlist.i_pes_end = 0;
-#endif
-
-    /* Initialize all iovec from the TS netlist with the length of a packet */
-    for( i_iovec = 0; i_iovec < INPUT_MAX_TS + INPUT_TS_READ_ONCE; i_iovec++ )
-    {
-        p_input->netlist.p_ts_free[i_iovec].iov_len = TS_PACKET_SIZE;
-    }
-
-    /* Allocate a big piece of memory to contain the INPUT_MAX_TS TS packets */
-    if( ( p_input->netlist.p_ts_packets = malloc( (INPUT_MAX_TS + 1)
-                                             * sizeof(ts_packet_t) ) ) == NULL )
-    {
-        intf_ErrMsg("input error: can't allocate TS netlist buffer (%s)\n",
-                    strerror(errno) );
-        return( -1 );
-    }
-
-  /* Allocate a big piece of memory to contain the INPUT_MAX_PES PES packets */
-    if( !( p_input->netlist.p_pes_packets = malloc( (INPUT_MAX_PES + 1)
-                                             * sizeof(pes_packet_t) ) ) )
-    {
-        intf_ErrMsg("input error: can't allocate PES netlist buffer (%s)\n",
-                    strerror(errno) );
-        free( p_input->netlist.p_ts_packets );
-        return( -1 );
-    }
-
-    /* Insert TS packets into the TS netlist */
-#ifdef INPUT_LIFO_TS_NETLIST
-    i_base = p_input->netlist.i_ts_index;
-#else
-    i_base = p_input->netlist.i_ts_start;
-#endif
-    /* i_base is now the base address to locate free packets in the netlist */
-
-    for( i_packets = 0; i_packets < INPUT_MAX_TS + 1; i_packets++ )
-    {
-        p_input->netlist.p_ts_free[i_base + i_packets].iov_base
-                          = (void *)(p_input->netlist.p_ts_packets + i_packets);
-        /* Initialize TS length. */
-        (p_input->netlist.p_ts_packets[i_packets]).i_payload_end = TS_PACKET_SIZE;
-    }
-
-    /* Insert PES packets into the netlist */
-#ifdef INPUT_LIFO_PES_NETLIST
-    i_base = p_input->netlist.i_pes_index;
-#else
-    i_base = p_input->netlist.i_pes_start;
-#endif
-    /* i_base is now the base address to locate free packets in the netlist */
-
-    for( i_packets = 0; i_packets < INPUT_MAX_PES + 1; i_packets++ )
-    {
-        p_input->netlist.p_pes_free[i_base + i_packets]
-                              = p_input->netlist.p_pes_packets + i_packets;
-    }
-
-    /* the p_pes_header_save buffer is allocated on the fly by the PES
-       demux if needed, and freed with the PES packet when the netlist
-       is destroyed. We initialise the field to NULL so that the demux
-       can determine if it has already allocated this buffer or not. */
-    for( i_packets = 0; i_packets < INPUT_MAX_PES + 1; i_packets++ )
-    {
-      p_input->netlist.p_pes_packets[i_packets].p_pes_header_save = NULL;
-    }
-
-    return( 0 );
-}
-
-/*****************************************************************************
- * input_NetlistClean: clean the netlists buffers
- *****************************************************************************/
-void input_NetlistEnd( input_thread_t *p_input )
-{
-    int i;
-
-    /* free TS netlist */
-    free( p_input->netlist.p_ts_packets );
-
-    /* free the pes_buffer_save buffers of the PES packets if they have
-       been allocated */
-    for( i = 0; i < INPUT_MAX_PES + 1; i++ )
-    {
-        byte_t* p_buffer = p_input->netlist.p_pes_packets[i].p_pes_header_save;
-        if(p_buffer)
-            free(p_buffer);
-    }
-
-    /* free PES netlist */
-    free( p_input->netlist.p_pes_packets );
-}
-
diff --git a/src/input/input_network.c b/src/input/input_network.c
deleted file mode 100644 (file)
index d59b8b0..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*****************************************************************************
- * network.c: functions to read from the network
- * Manages a socket.
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *          Benoît Steiner <benny@via.ecp.fr>
- *
- * 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 <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
-#include <string.h>                                            /* strerror() */
-#include <unistd.h>                                               /* close() */
-#include <errno.h>                                                  /* errno */
-#include <sys/time.h>                                   /* "input_network.h" */
-
-#if defined(SYS_BSD) || defined(SYS_BEOS)
-#include <sys/socket.h>                                   /* struct sockaddr */
-#endif
-
-#include <netdb.h>     /* servent, getservbyname(), hostent, gethostbyname() */
-#include <netinet/in.h>                     /* sockaddr_in, htons(), htonl() */
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "netutils.h"
-
-#include "input.h"
-#include "input_network.h"
-#include "input_vlan.h"
-
-#include "intf_msg.h"
-#include "plugins.h"
-#include "main.h"
-
-/*****************************************************************************
- * input_NetworkOpen: initialize a network stream
- *****************************************************************************/
-int input_NetworkOpen( input_thread_t *p_input )
-{
-    int                     i_socket_option;
-    struct sockaddr_in      sa_in;
-    char                    psz_hostname[INPUT_MAX_SOURCE_LENGTH];
-
-    /* First and foremost, in the VLAN method, join the desired VLAN. */
-    if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
-    {
-        if( input_VlanJoin( p_input->i_vlan ) )
-        {
-            intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
-            return( 1 );
-        }
-    }
-
-    /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
-     * protocol */
-    if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
-    {
-        intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
-        return( 1 );
-    }
-
-    /*
-     * Set up the options of the socket
-     */
-
-    /* Set SO_REUSEADDR option which allows to re-bind() a busy port */
-    i_socket_option = 1;
-    if( setsockopt( p_input->i_handle,
-                    SOL_SOCKET,
-                    SO_REUSEADDR,
-                    &i_socket_option,
-                    sizeof( i_socket_option ) ) == (-1) )
-    {
-        intf_ErrMsg("error: can't configure socket (SO_REUSEADDR: %s)\n", strerror(errno));
-        close( p_input->i_handle );
-        return( 1 );
-    }
-
-#ifndef SYS_BEOS
-    /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
-     * packet loss caused by scheduling problems */
-    i_socket_option = 524288;
-    if( setsockopt( p_input->i_handle,
-                    SOL_SOCKET,
-                    SO_RCVBUF,
-                    &i_socket_option,
-                    sizeof( i_socket_option ) ) == (-1) )
-    {
-        intf_ErrMsg("error: can't configure socket (SO_RCVBUF: %s)\n", strerror(errno));
-        close( p_input->i_handle );
-        return( 1 );
-    }
-#endif /* SYS_BEOS */
-
-    /*
-     * Bind the socket
-     */
-
-    /* Use default port if not specified */
-    if( p_input->i_port == 0 )
-    {
-        p_input->i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
-    }
-
-    /* See if the user requested broadcast method */
-    if( main_GetIntVariable( INPUT_BROADCAST_VAR, INPUT_BROADCAST_DEFAULT ) )
-    {
-        p_input->i_method = INPUT_METHOD_TS_BCAST;
-    }
-
-    /* Find the address. */
-    switch( p_input->i_method )
-    {
-    case INPUT_METHOD_TS_BCAST:
-    case INPUT_METHOD_TS_VLAN_BCAST:
-        /* In that case, we have to bind with the broadcast address.
-         * broadcast addresses are very hard to find and depends on
-         * implementation, so we thought using a #define would be much
-         * simpler. */
-#ifdef INPUT_BCAST_ADDR
-        if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
-        {
-            close( p_input->i_handle );
-            return( 1 );
-        }
-#else
-        /* We bind with any address. Security problem ! */
-        if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
-        {
-            close( p_input->i_handle );
-            return( -1 );
-        }
-#endif
-        break;
-
-    case INPUT_METHOD_TS_UCAST:
-        /* Unicast: bind with the local address. */
-        if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
-        {
-            intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
-            close( p_input->i_handle );
-            return( 1 );
-        }
-        if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
-        {
-            close( p_input->i_handle );
-            return( 1 );
-        }
-        break;
-
-    case INPUT_METHOD_TS_MCAST:
-        /* Multicast: bind with 239.0.0.1. */
-        if( BuildInetAddr( &sa_in, "239.0.0.1", p_input->i_port ) == (-1) )
-        {
-            close( p_input->i_handle );
-            return( 1 );
-        }
-        break;
-    }
-
-    /* Effectively bind the socket. */
-    if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
-    {
-        intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
-        close( p_input->i_handle );
-        return( 1 );
-    }
-
-    /*
-     * Connect the socket to the remote server
-     */
-
-    /* Use default host if not specified */
-    if( p_input->p_source == NULL )
-    {
-        p_input->p_source = main_GetPszVariable( INPUT_SERVER_VAR, INPUT_SERVER_DEFAULT );
-    }
-
-    if( BuildInetAddr( &sa_in, p_input->p_source, htons(0) ) == (-1) )
-    {
-        close( p_input->i_handle );
-        return( -1 );
-    }
-
-    /* Connect the socket. */
-    if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
-                 sizeof( sa_in ) ) == (-1) )
-    {
-        intf_ErrMsg("error: can't connect socket\n" );
-        close( p_input->i_handle );
-        return( 1 );
-    }
-    return( 0 );
-}
-
-/*****************************************************************************
- * input_NetworkRead: read a stream from the network
- *****************************************************************************
- * Wait for data during up to 1 second and then abort if none is arrived. The
- * number of bytes read is returned or -1 if an error occurs (so 0 is returned
- * after a timeout)
- * We don't have to make any test on presentation times, since we suppose
- * the network server sends us data when we need it.
- *****************************************************************************/
-int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
-                       size_t i_count )
-{
-    fd_set rfds;
-    struct timeval tv;
-    int i_rc;
-
-    /* Watch the given fd to see when it has input */
-    FD_ZERO(&rfds);
-    FD_SET(p_input->i_handle, &rfds);
-
-    /* Wait up to 1 second */
-    tv.tv_sec = 1;
-    tv.tv_usec = 0;
-
-    i_rc = select(p_input->i_handle+1, &rfds, NULL, NULL, &tv);
-
-    if( i_rc > 0 )
-    {
-        /* Data were received before timeout */
-        i_rc = readv( p_input->i_handle, p_vector, i_count );
-    }
-
-    return( i_rc );
-}
-
-/*****************************************************************************
- * input_NetworkClose: close a network stream
- *****************************************************************************/
-void input_NetworkClose( input_thread_t *p_input )
-{
-    /* Close local socket. */
-    if( p_input->i_handle )
-    {
-        close( p_input->i_handle );
-    }
-
-    /* Leave vlan if required */
-    if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
-    {
-        input_VlanLeave( p_input->i_vlan );
-    }
-}
-
diff --git a/src/input/input_network.h b/src/input/input_network.h
deleted file mode 100644 (file)
index 7e1c616..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * input_network.h: network functions interface
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Christophe Massiot <massot@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int input_NetworkOpen   ( input_thread_t *p_input );
-int input_NetworkRead   ( input_thread_t *p_input, const struct iovec *p_vector,
-                          size_t i_count );
-void input_NetworkClose ( input_thread_t *p_input );
diff --git a/src/input/input_pcr.c b/src/input/input_pcr.c
deleted file mode 100644 (file)
index 16e3e4a..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*****************************************************************************
- * pcr.c: PCR management
- * Manages structures containing PCR information.
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
- *
- * 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 <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
-#include <stdlib.h>                              /* atoi(), malloc(), free() */
-#include <netinet/in.h>                                           /* ntohl() */
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "debug.h"
-#include "input.h"
-#include "intf_msg.h"
-#include "input_pcr.h"
-
-/* Note:
- *
- *   SYNCHRONIZATION METHOD
- *
- *   We compute an average for the pcr because we want to eliminate the
- *   network jitter and keep the low frequency variations. The average is
- *   in fact a low pass filter and the jitter is a high frequency signal
- *   that is why it is eliminated by the filter/average.
- *
- *   The low frequency variations enable us to synchronize the client clock
- *   with the server clock because they represent the time variation between
- *   the 2 clocks. Those variations (ie the filtered pcr) are used to compute
- *   the presentation dates for the audio and video frames. With those dates
- *   we can decoding (or trashing) the MPEG2 stream at "exactly" the same rate
- *   as it is sent by the server and so we keep the synchronization between
- *   the server and the client.
- *
- *   It is a very important matter if you want to avoid underflow or overflow
- *   in all the FIFOs, but it may be not enough.
- *
- */
-
-/*****************************************************************************
- * input_PcrReInit : Reinitialize the pcr_descriptor
- *****************************************************************************/
-void input_PcrReInit( input_thread_t *p_input )
-{
-    ASSERT( p_input );
-
-    p_input->p_pcr->delta_pcr       = 0;
-    p_input->p_pcr->last_pcr        = 0;
-    p_input->p_pcr->c_average_count = 0;
-}
-
-/*****************************************************************************
- * input_PcrInit : Initialize PCR decoder
- *****************************************************************************/
-int input_PcrInit( input_thread_t *p_input )
-{
-    ASSERT( p_input );
-
-    if( (p_input->p_pcr = malloc(sizeof(pcr_descriptor_t))) == NULL )
-    {
-        return( -1 );
-    }
-    input_PcrReInit(p_input);
-    p_input->p_pcr->i_synchro_state = SYNCHRO_NOT_STARTED;
-
-    return( 0 );
-}
-
-/*****************************************************************************
- * input_PcrDecode : Decode a PCR frame
- *****************************************************************************/
-void input_PcrDecode( input_thread_t *p_input, es_descriptor_t *p_es,
-                      u8* p_pcr_data )
-{
-    mtime_t pcr_time, sys_time, delta_pcr;
-    pcr_descriptor_t *p_pcr;
-
-    ASSERT( p_pcr_data );
-    ASSERT( p_input );
-    ASSERT( p_es );
-
-    p_pcr = p_input->p_pcr;
-
-    /* Convert the PCR in microseconde
-     * WARNING: do not remove the casts in the following calculation ! */
-    pcr_time  = ( (( (mtime_t)U32_AT((u32*)p_pcr_data) << 1 ) | ( p_pcr_data[4] >> 7 )) * 300 ) / 27;
-    sys_time  = mdate();
-    delta_pcr = sys_time - pcr_time;
-
-    if( p_es->b_discontinuity ||
-        ( p_pcr->last_pcr != 0 &&
-              (    (p_pcr->last_pcr - pcr_time) > PCR_MAX_GAP
-                || (p_pcr->last_pcr - pcr_time) < - PCR_MAX_GAP ) ) )
-    {
-        intf_DbgMsg("input debug: input_PcrReInit()\n");
-        input_PcrReInit(p_input);
-        p_pcr->i_synchro_state = SYNCHRO_REINIT;
-        p_es->b_discontinuity = 0;
-    }
-    p_pcr->last_pcr = pcr_time;
-
-    if( p_pcr->c_average_count == PCR_MAX_AVERAGE_COUNTER )
-    {
-        p_pcr->delta_pcr =
-            ( delta_pcr + (p_pcr->delta_pcr * (PCR_MAX_AVERAGE_COUNTER-1)) )
-            / PCR_MAX_AVERAGE_COUNTER;
-    }
-    else
-    {
-        p_pcr->delta_pcr =
-            ( delta_pcr + (p_pcr->delta_pcr * p_pcr->c_average_count) )
-            / ( p_pcr->c_average_count + 1 );
-        p_pcr->c_average_count++;
-    }
-
-    if( p_pcr->i_synchro_state == SYNCHRO_NOT_STARTED )
-    {
-        p_pcr->i_synchro_state = SYNCHRO_START;
-    }
-}
-
-/*****************************************************************************
- * input_PcrEnd : Clean PCR structures before dying
- *****************************************************************************/
-void input_PcrEnd( input_thread_t *p_input )
-{
-    ASSERT( p_input );
-
-    free( p_input->p_pcr );
-}
diff --git a/src/input/input_pcr.h b/src/input/input_pcr.h
deleted file mode 100644 (file)
index 8c25582..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*****************************************************************************
- * input_pcr.h: PCR management interface
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-/* Maximum number of samples used to compute the dynamic average value,
- * it is also the maximum of c_average in the pcr_descriptor_struct.
- * We use the following formula :
- * new_average = (old_average * c_average + new_sample_value) / (c_average +1) */
-#define PCR_MAX_AVERAGE_COUNTER 40
-
-/* Maximum gap allowed between two PCRs. */
-#define PCR_MAX_GAP 1000000
-
-/* synchro states */
-#define SYNCHRO_NOT_STARTED 1
-#define SYNCHRO_START       2
-#define SYNCHRO_REINIT      3
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int            input_PcrInit        ( input_thread_t *p_input );
-void           input_PcrDecode      ( input_thread_t *p_input, es_descriptor_t* p_es,
-                                       u8* p_pcr_data );
-void           input_PcrEnd         ( input_thread_t *p_input );
diff --git a/src/input/input_ps.c b/src/input/input_ps.c
new file mode 100644 (file)
index 0000000..e0f9646
--- /dev/null
@@ -0,0 +1,317 @@
+/*****************************************************************************
+ * input_ps.c: PS demux and packet management
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000 VideoLAN
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h"
+
+#include "stream_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
+
+#include "input.h"
+
+#include "input_ps.h"
+#include "mpeg_system.h"
+
+#include "debug.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int  PSProbe     ( struct input_thread_s * );
+static void PSRead      ( struct input_thread_s *,
+                          data_packet_t * p_packets[INPUT_READ_ONCE] );
+static void PSInit      ( struct input_thread_s * );
+static void PSEnd       ( struct input_thread_s * );
+static struct data_packet_s * NewPacket ( void *, size_t );
+static void DeletePacket( void *, struct data_packet_s * );
+static void DeletePES   ( void *, struct pes_packet_s * );
+
+/*
+ * Data reading functions
+ */
+
+/*****************************************************************************
+ * PSProbe: verifies that the stream is a PS stream
+ *****************************************************************************/
+static int PSProbe( input_thread_t * p_input )
+{
+    /* verify that the first three bytes are 0x000001, or unscramble and
+     * re-do. */
+    return 1;
+}
+
+/*****************************************************************************
+ * PSInit: initializes PS structures
+ *****************************************************************************/
+static void PSInit( input_thread_t * p_input )
+{
+    thread_ps_data_t *  p_method;
+    stream_ps_data_t *  p_demux;
+
+    if( (p_method =
+         (thread_ps_data_t *)malloc( sizeof(thread_ps_data_t) )) == NULL )
+    {
+        intf_ErrMsg( "Out of memory" );
+        p_input->b_error = 1;
+        return;
+    }
+
+    p_input->p_method_data = (void *)p_method;
+
+    /* Re-open the socket as a buffered FILE stream */
+    if( (p_method->stream = fdopen( p_input->i_handle, "r" )) == NULL )
+    {
+        intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
+        p_input->b_error = 1;
+        return;
+    }
+    fseek( p_method->stream, 0, SEEK_SET );
+
+    /* Pre-parse the stream to gather stream_descriptor_t. */
+
+    /* FIXME */
+    p_input->stream.pp_programs =
+         (pgrm_descriptor_t **)malloc( sizeof(pgrm_descriptor_t *) );
+    p_input->stream.pp_programs[0] =
+         (pgrm_descriptor_t *)malloc( sizeof(pgrm_descriptor_t) );
+    p_input->stream.pp_programs[0]->i_synchro_state = SYNCHRO_START;
+    p_input->stream.pp_programs[0]->delta_cr = 0;
+    p_input->stream.pp_programs[0]->last_cr = 0;
+    p_input->stream.pp_programs[0]->c_average_count = 0;
+
+    p_demux = (stream_ps_data_t *)malloc( sizeof( stream_ps_data_t) );
+    p_input->stream.p_demux_data = (void *)p_demux;
+    p_demux->b_is_PSM_complete = 0;
+}
+
+/*****************************************************************************
+ * PSEnd: frees unused data
+ *****************************************************************************/
+static void PSEnd( input_thread_t * p_input )
+{
+    free( p_input->stream.p_demux_data );
+    free( p_input->p_method_data );
+}
+
+/*****************************************************************************
+ * PSRead: reads a data packet
+ *****************************************************************************/
+/* FIXME: read INPUT_READ_ONCE packet at once */
+static void PSRead( input_thread_t * p_input,
+                    data_packet_t * p_packets[INPUT_READ_ONCE] )
+{
+    byte_t              p_header[6];
+    data_packet_t *     p_data;
+    int                 i_packet_size;
+    thread_ps_data_t *  p_method;
+
+    p_method = (thread_ps_data_t *)p_input->p_method_data;
+
+    while( fread( p_header, 6, 1, p_method->stream ) != 1 )
+    {
+        int             i_error;
+        if( (i_error = ferror( p_method->stream )) )
+        {
+            intf_ErrMsg( "Read 1 failed (%s)", strerror(i_error) );
+            p_input->b_error = 1;
+            return;
+        }
+
+        if( feof( p_method->stream ) )
+        {
+            intf_ErrMsg( "EOF reached" );
+            p_input->b_error = 1;
+            return;
+        }
+    }
+
+    if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
+    {
+        u32         i_buffer = U32_AT(p_header);
+        intf_ErrMsg( "Garbage at input (%x)\n", i_buffer );
+        while( (i_buffer & 0xFFFFFF00) != 0x100L )
+        {
+            i_buffer <<= 8;
+            i_buffer |= getc( p_method->stream );
+            if( feof(p_method->stream) || ferror(p_method->stream) )
+            {
+                p_input->b_error = 1;
+                return;
+            }
+        }
+        *(u32 *)p_header = i_buffer;
+        fread( p_header + 4, 2, 1, p_method->stream );
+    }
+
+    if( U32_AT(p_header) != 0x1BA )
+    {
+        i_packet_size = U16_AT(&p_header[4]);
+    }
+    else
+    {
+        i_packet_size = 8;
+    }
+
+    if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
+    {
+        p_input->b_error = 1;
+        intf_ErrMsg( "Out of memory" );
+        return;
+    }
+
+    memcpy( p_data->p_buffer, p_header, 6 );
+
+    /* FIXME: catch EINTR ! */
+    while( fread( p_data->p_buffer + 6, i_packet_size,
+               1, p_method->stream ) != 1 )
+    {
+        int             i_error;
+        if( (i_error = ferror( p_method->stream)) )
+        {
+            intf_ErrMsg( "Read 1 failed (%s)", strerror(i_error) );
+            p_input->b_error = 1;
+            return;
+        }
+
+        if( feof( p_method->stream ) )
+        {
+            intf_ErrMsg( "EOF reached" );
+            p_input->b_error = 1;
+            return;
+        }
+    }
+
+    if( U32_AT(p_header) == 0x1BA )
+    {
+        /* stuffing_bytes */
+        byte_t      p_garbage[8];
+        /* FIXME: catch EINTR ! */
+        if( (p_data->p_buffer[13] & 0x3) != 0 )
+        {
+            fread( p_garbage, p_garbage[0] & 0x3, 1,
+                   p_method->stream );
+        }
+    }
+
+    memset( p_packets, 0, sizeof(p_packets) );
+    p_packets[0] = p_data;
+}
+
+
+/*
+ * Packet management utilities
+ */
+
+/*****************************************************************************
+ * NewPacket: allocates a data packet
+ *****************************************************************************/
+static struct data_packet_s * NewPacket( void * p_garbage,
+                                         size_t i_size )
+{
+    data_packet_t * p_data;
+
+    if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL )
+    {
+        intf_DbgMsg( "Out of memory" );
+        return NULL;
+    }
+
+    if( (p_data->p_buffer = (byte_t *)malloc( i_size )) == NULL )
+    {
+        intf_DbgMsg( "Out of memory" );
+        free( p_data );
+        return NULL;
+    }
+
+    p_data->p_payload_start = p_data->p_buffer;
+    p_data->p_payload_end = p_data->p_buffer + i_size;
+
+    return( p_data );
+}
+
+/*****************************************************************************
+ * DeletePacket: deletes a data packet
+ *****************************************************************************/
+static void DeletePacket( void * p_garbage,
+                          data_packet_t * p_data )
+{
+    ASSERT(p_data);
+    ASSERT(p_data->p_buffer);
+    free( p_data->p_buffer );
+    free( p_data );
+}
+
+/*****************************************************************************
+ * DeletePES: deletes a PES packet and associated data packets
+ *****************************************************************************/
+static void DeletePES( void * p_garbage, pes_packet_t * p_pes )
+{
+    data_packet_t *     p_data;
+    data_packet_t *     p_next;
+
+    p_data = p_pes->p_first;
+
+    while( p_data != NULL )
+    {
+        p_next = p_data->p_next;
+        free( p_data->p_buffer );
+        free( p_data );
+        p_data = p_next;
+    }
+
+    free( p_pes );
+}
+
+/*****************************************************************************
+ * PSKludge: fakes a PS plugin (FIXME)
+ *****************************************************************************/
+input_capabilities_t * PSKludge( void )
+{
+    input_capabilities_t *  p_plugin;
+
+    p_plugin = (input_capabilities_t *)malloc( sizeof(input_capabilities_t) );
+    p_plugin->pf_init = PSInit;
+    p_plugin->pf_read = PSRead;
+    p_plugin->pf_demux = input_DemuxPS; /* FIXME: use i_p_config_t ! */
+    p_plugin->pf_new_packet = NewPacket;
+    p_plugin->pf_delete_packet = DeletePacket;
+    p_plugin->pf_delete_pes = DeletePES;
+    p_plugin->pf_rewind = NULL;
+    p_plugin->pf_seek = NULL;
+
+    return( p_plugin );
+}
diff --git a/src/input/input_ps.h b/src/input/input_ps.h
new file mode 100644 (file)
index 0000000..4dd155e
--- /dev/null
@@ -0,0 +1,12 @@
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+
+/*****************************************************************************
+ * thread_ps_data_t: extension of input_thread_t
+ *****************************************************************************/
+typedef struct thread_ps_data_s
+{
+    /* We're necessarily reading a file. */
+    FILE *                  stream;
+} thread_ps_data_t;
diff --git a/src/input/input_psi.c b/src/input/input_psi.c
deleted file mode 100644 (file)
index fccb7a9..0000000
+++ /dev/null
@@ -1,1357 +0,0 @@
-/*****************************************************************************
- * psi.c: PSI management
- * Manages structures containing PSI information, and affiliated decoders.
- * TODO: Fonctions d'init des structures
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Benoît Steiner <benny@via.ecp.fr>
- *
- * 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 <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                            /* "input.h" */
-#include <stdlib.h>                                     /* free(), realloc() */
-#include <string.h>                                               /* bzero() */
-#include <netinet/in.h>                                           /* ntohs() */
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "intf_msg.h"
-#include "plugins.h"
-#include "debug.h"
-
-#include "input.h"
-#include "input_ctrl.h"
-#include "input_psi.h"
-
-#include "main.h"
-
-/*
- * Precalculated 32-bits CRC table, shared by all instances of the PSI decoder
- */
-boolean_t b_crc_initialised = 0;
-u32 i_crc_32_table[256];
-
-/*
- * Global configuration variable, need by AUTO_SPAWN to determine
- * the option (audio and video) passed to the VideoLAN client.
- */
-#ifdef AUTO_SPAWN
-//XXX?? extern program_data_t *p_main;
-#endif
-
-/*
- * Locale type definitions
- */
-#define PSI_VIDEO_STREAM_DESCRIPTOR                 0x02
-#define PSI_AUDIO_STREAM_DESCRIPTOR                 0x03
-#define PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR       0x07
-#define PSI_VIDEO_WINDOW_DESCRIPTOR                 0x08
-
-#ifdef DVB_EXTENSIONS
-#define PSI_SERVICE_DESCRIPTOR                      0x48
-#endif
-
-/* That info must be stored in the version field since it contains
-   unused bits */
-#define PSI_UNINITIALISED                           0xFF
-
-/*
- * Local prototypes
- */
-static int input_AddPsiPID( input_thread_t *p_input, int i_pid );
-static int input_DelPsiPID( input_thread_t *p_input, int i_pid );
-static void DecodePgrmAssocSection( byte_t* p_pas, input_thread_t *p_input );
-static void DecodePgrmMapSection( byte_t* p_pms, input_thread_t *p_input );
-static void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input );
-static void DecodePgrmDescriptor( byte_t* p_descr, pgrm_descriptor_t* p_pgrm );
-static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es );
-
-static stream_descriptor_t* AddStreamDescr( input_thread_t* p_input,
-                                            u16 i_stream_id );
-static void DestroyStreamDescr( input_thread_t* p_input, u16 i_stream_id );
-static pgrm_descriptor_t* AddPgrmDescr( stream_descriptor_t* p_stream,
-                                       u16 i_pgrm_id );
-static void DestroyPgrmDescr( input_thread_t* p_input,
-                              stream_descriptor_t* p_stream, u16 i_pgrm_id );
-static es_descriptor_t* AddESDescr( input_thread_t* p_input,
-                                    pgrm_descriptor_t* p_pgrm, u16 i_es_pid );
-static void DestroyESDescr( input_thread_t* p_input, pgrm_descriptor_t* p_pgrm,
-                            u16 i_es_pid);
-
-static void BuildCrc32Table();
-static int CheckCRC32( u8* p_pms, int i_size);
-static boolean_t Is_known( byte_t* a_known_section, u8 i_section );
-static void Set_known( byte_t* a_known_section, u8 i_section );
-static void Unset_known( byte_t* a_known_section, u8 i_section );
-
-/*****************************************************************************
- * input_PsiInit: Initialize PSI decoder
- *****************************************************************************
- * Init the structures in which the PSI decoder will put the informations it
- * got from PSI tables and request for the reception of the PAT.
- *****************************************************************************/
-int input_PsiInit( input_thread_t *p_input )
-{
-  ASSERT(p_input);
-
-  /* Precalculate the 32-bit CRC table if not already done ?
-     FIXME: Put a lock or do that at pgrm init ?? */
-  if( !b_crc_initialised )
-  {
-    BuildCrc32Table();
-    b_crc_initialised = 1;
-  }
-
-  /* Init the structure that describes the stream we are receiving */
-  AddStreamDescr( p_input, PSI_UNINITIALISED );
-
-  /* Request for reception of the program association table */
-  input_AddPsiPID( p_input, 0 );
-
-#ifdef DVB_EXTENSIONS
-  /* Request for reception of the service description table */
-  input_AddPsiPID( p_input, 17 );
-#endif
-
-  return( 0 );
-}
-
-/*****************************************************************************
- * input_PsiClean: Clean PSI structures before dying
- *****************************************************************************/
-int input_PsiEnd( input_thread_t *p_input )
-{
-  ASSERT(p_input);
-
-  /* Stop to receive all the PSI tables associated with that program */
-  /* FIXME: Not really useful ??*/
-
-  /* Clean also descriptors for programs associated with that stream */
-  /* FIXME: -> Not really useful and maybe buggy ??*/
-
-  /* Destroy the stream description */
-  DestroyStreamDescr( p_input, p_input->p_stream->i_stream_id );
-
-  return( 0 );
-}
-
-/*****************************************************************************
- * input_PsiRead: Read the table of programs
- *****************************************************************************
- * Ugly debugging function at that time ? XXX??
- *****************************************************************************/
-void input_PsiRead( input_thread_t *p_input /* XXX?? */ )
-{
-  int i_index;
-  int i_index2;
-  pgrm_descriptor_t* p_pgrm;
-
-  ASSERT( p_input );
-
-  /* Lock the tables, since this method can be called from any thread */
-  //vlc_mutex_lock()
-
-  /* Check if the table is complete or not */
-  if( !p_input->p_stream->b_is_PMT_complete )
-  {
-    intf_IntfMsg( "Warning: PMT not yet complete\n" );
-  }
-
-  /* Read the table */
-  for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
-  {
-    p_pgrm = p_input->p_stream->ap_programs[i_index];
-    intf_DbgMsg("Printing info for program %d\n", p_pgrm->i_number );
-    intf_IntfMsg("Printing info for program %d\n", p_pgrm->i_number );
-
-    for( i_index2 = 0; i_index2 < p_pgrm->i_es_number; i_index2++ )
-    {
-      intf_DbgMsg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n",
-                   p_pgrm->ap_es[i_index2]->i_id,
-                   p_pgrm->ap_es[i_index2]->i_type,
-                   p_pgrm->ap_es[i_index2]->b_pcr,
-                   p_pgrm->ap_es[i_index2]->b_psi);
-
-      intf_IntfMsg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n",
-                    p_pgrm->ap_es[i_index2]->i_id,
-                    p_pgrm->ap_es[i_index2]->i_type,
-                    p_pgrm->ap_es[i_index2]->b_pcr,
-                    p_pgrm->ap_es[i_index2]->b_psi);
-    }
-  }
-
-  /* Unock the tables */
-  //vlc_mutex_unlock()
-}
-
-/*****************************************************************************
- * input_PsiDecode: Decode a PSI section
- *****************************************************************************
- * This funtion is essentially a wrapper that will  perform basic checks on
- * the section and then call the right function according to its type.
- *****************************************************************************/
-void input_PsiDecode( input_thread_t *p_input, psi_section_t* p_psi_section )
-{
-  ASSERT(p_input);
-  ASSERT(p_psi_section);
-
-  /* Hexa dump of the beginning of the section (for real men) */
-  //intf_DbgMsg( "Section: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", (u8)p_psi_section->buffer[0], (u8)p_psi_section->buffer[1], (u8)p_psi_section->buffer[2], (u8)p_psi_section->buffer[3], (u8)p_psi_section->buffer[4], (u8)p_psi_section->buffer[5], (u8)p_psi_section->buffer[6], (u8)p_psi_section->buffer[7], (u8)p_psi_section->buffer[8], (u8)p_psi_section->buffer[9], (u8)p_psi_section->buffer[10], (u8)p_psi_section->buffer[11], (u8)p_psi_section->buffer[12], (u8)p_psi_section->buffer[13], (u8)p_psi_section->buffer[14], (u8)p_psi_section->buffer[15], (u8)p_psi_section->buffer[16], (u8)p_psi_section->buffer[17], (u8)p_psi_section->buffer[18], (u8)p_psi_section->buffer[19] );
-
-  /* Check the CRC validity if any CRC is carried */
-#if 0
-  if( p_psi_section->buffer[1] & 0x80 )
-  {
-    if( CheckCRC32 (p_psi_section->buffer, p_psi_section->i_length) )
-    {
-      intf_DbgMsg("iSize: %d, CRC: %d\n", p_psi_section->i_length,
-                  U32_AT(&p_psi_section->buffer[p_psi_section->i_length-4]));
-      intf_DbgMsg( "Invalid CRC for PSI\n" );
-      return;
-    }
-  }
-#endif
-
-  /* If the section is not immediatly applicable, trash it (DVB drafts disallow
-     transmission of such sections, so we didn't implement it) */
-  if( !p_psi_section->buffer[5] & 0x01 )
-  {
-    intf_DbgMsg( "PSI not yet applicable: trash it\n" );
-    return;
-  }
-
-  /* Handle the packet according to it's type given it the table_id  */
-  switch ( p_psi_section->buffer[0] )
-  {
-    case 0x00:
-      //intf_DbgMsg("Program association section received\n");
-      DecodePgrmAssocSection(p_psi_section->buffer, p_input);
-      break;
-    case 0x01:
-      //intf_DbgMsg("Conditional access section received\n");
-      break;
-    case 0x02:
-      //intf_DbgMsg("Program map section received\n");
-      DecodePgrmMapSection(p_psi_section->buffer, p_input);
-      break;
-    case 0x42:
-      //intf_DbgMsg("Service description section received\n");
-      DecodeSrvDescrSection(p_psi_section->buffer, p_input);
-      break;
-    default:
-      //intf_DbgMsg("Private PSI data received (type %x), ignoring it\n",
-      //            p_psi_section->buffer[0]);
-  }
-}
-
-/*****************************************************************************
- * DecodeAssocSection: Decode a PAS
- *****************************************************************************
- * No check is made to known if the table is currently applicable or not, so
- * that unapplicable sections must be filtered before calling this function
- * The Program Association Table can be segmented to occupy multiple sections
- * so that we have to know which sections we have already received (IsKnown() /
- * SetKnown() calls)
- *****************************************************************************/
-static void DecodePgrmAssocSection(u8* p_pas, input_thread_t *p_input )
-{
-    u8 i_stream_id;            /* Id of the stream described in that section */
-    u8 i_version;             /* Version of the table carried in the section */
-
-    u16 i_pgrm_id;                      /* Id of the current described  pgrm */
-    u16 i_pgrm_map_pid;           /* PID of the associated program map table */
-    int i_pgrm_number;        /* Number of programs described in the section */
-
-    boolean_t b_is_invalid = 0;
-
-    u8 i_current_section;
-    u8 i_last_section;
-
-    int i_pgrm_index;
-    int i_es_index;
-
-    ASSERT(p_pas);
-    ASSERT(p_input);
-
-#define p_descr (p_input->p_stream)
-
-    /* Read stream id and version number immediately, to be sure they will be
-       initialised in all cases we will need it */
-    i_stream_id = U16_AT(&p_pas[3]);
-    i_version = (p_pas[5] >> 1) & 0x1F;
-    //intf_DbgMsg("TS Id: %d, version: %d\n", U16_AT(&p_pas[3]),(p_pas[5] >> 1) & 0x1F);
-
-    /* Test if the stream has not changed by looking at the stream_id */
-    if( p_descr->i_stream_id != i_stream_id )
-    {
-        /* This can either mean that the PSI decoder has just started or that
-           the stream has changed */
-        if( p_descr->i_PAT_version== PSI_UNINITIALISED )
-            intf_DbgMsg("Building Program Association table\n");
-        else
-            intf_ErrMsg( "Stream Id has suddenly changed ! Rebuilding PAT\n" );
-
-        /* Whatever it is, ask the PSI decoder to rebuild the table */
-        b_is_invalid = 1;
-    }
-    else
-    {
-        /* Stream has not changed, test if the PMT is up to date */
-        if( p_descr->i_PAT_version != i_version )
-        {
-            intf_DbgMsg("PAT has been updated, rebuilding it\n");
-            /* Ask the PSI decoder to rebuild the table */
-            b_is_invalid = 1;
-        }
-    }
-
-    /* Clear the table if needed */
-    if( b_is_invalid )
-    {
-        intf_DbgMsg("Updating PAT table\n");
-
-        /* Any program in the stream may have disapeared, or a new one
-           can have been added. The good way to handle such a case would be
-           to build a temporary table and to make a diff */
-
-        /* Stop the reception of all programs and PSI informations
-           associated with this stream, excepted the PAT on PID 0 and the SDT
-           on PID 17 */
-        for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES &&
-             p_input->pp_selected_es[i_es_index]; i_es_index++ )
-        {
-          if( p_input->pp_selected_es[i_es_index]->b_psi )
-          {
-            if( p_input->pp_selected_es[i_es_index]->i_id != 0
-#ifdef DVB_EXTENSIONS
-                && p_input->pp_selected_es[i_es_index]->i_id != 17
-#endif
-            )
-              input_DelPsiPID( p_input,
-                               p_input->pp_selected_es[i_es_index]->i_id );
-          }
-          else
-            input_DelPgrmElem( p_input,
-                               p_input->pp_selected_es[i_es_index]->i_id );
-        }
-
-        /* Recreate a new stream description. Since it is virgin, the decoder
-           will rebuild it entirely on is own */
-        DestroyStreamDescr(p_input, p_descr->i_stream_id);
-        AddStreamDescr(p_input, i_stream_id);
-
-        /* Record the new version for that table */
-        p_descr->i_PAT_version = i_version;
-    }
-
-    /* Build the table if not already complete or if it was cleared */
-    if( p_descr->b_is_PAT_complete )
-    {
-        /* Nothing to do */
-        if( b_is_invalid )
-            intf_DbgMsg("Bug: table invalid but PAT said to be complete\n");
-    }
-    else
-    {
-        /* Check if we already heard about that section */
-        i_last_section = p_pas[7];
-        i_current_section = p_pas[6];
-
-//        intf_DbgMsg( "Section %d (last section %d)\n",
-//                     i_current_section, i_last_section );
-
-        if( Is_known(p_descr->a_known_PAT_sections, i_current_section) )
-        {
-          /* Nothing to do */
-//          intf_DbgMsg("Section already received, skipping\n");
-        }
-        else
-        {
-          /* Compute the number of program_map PID carried in this section */
-          i_pgrm_number = ((U16_AT(&p_pas[1]) & 0xFFF) - 9) / 4;
-          intf_DbgMsg("Number of Pgrm in that section: %d\n", i_pgrm_number);
-
-          /* Start the reception of those program map PID */
-          for( i_pgrm_index = 0; i_pgrm_index < i_pgrm_number; i_pgrm_index++ )
-          {
-            i_pgrm_id = U16_AT(&p_pas[8+4*i_pgrm_index]);
-            i_pgrm_map_pid = U16_AT(&p_pas[8+4*i_pgrm_index+2]) & 0x1fff;
-            intf_DbgMsg("Pgrm %d described on pid %d\n", i_pgrm_id,
-                        i_pgrm_map_pid);
-
-            /* Check we are not already receiving that pid because it carries
-               info for another program */
-            for( i_es_index = 0; i_es_index < INPUT_MAX_ES; i_es_index++ )
-            {
-              if( p_input->p_es[i_es_index].i_id == i_pgrm_map_pid)
-              {
-                intf_DbgMsg("Already receiving pid %d", i_pgrm_map_pid);
-                i_es_index = INPUT_MAX_ES+1;
-                break;
-              }
-            }
-            /* Start to receive that PID if we're not already doing it */
-            if( i_es_index <= INPUT_MAX_ES )
-              input_AddPsiPID( p_input, i_pgrm_map_pid );
-
-            /* Append an entry to the pgrm_descriptor table to later store
-               the description of this program, unless program number is 0
-               (Network information table) */
-            if( i_pgrm_id != 0 )
-            {
-              intf_DbgMsg("Adding program %d to the PMT\n", i_pgrm_id);
-              AddPgrmDescr(p_descr, i_pgrm_id);
-            }
-          }
-
-          /* We now know the info carried in this section */
-          Set_known(p_descr->a_known_PAT_sections, i_current_section);
-
-          /* Check if the table is now complete */
-          p_descr->i_known_PAT_sections++;
-          if( p_descr->i_known_PAT_sections >= i_last_section)
-            p_descr->b_is_PAT_complete = 1;
-        }
-    }
-
-#undef p_descr
-}
-
-/*****************************************************************************
- * DecodePgrmMapSection: Decode a PMS
- *****************************************************************************
- * No check is made to known if the table is currently applicable or not, so
- * that unapplicable sections must be filtered before calling this function
- * The Program Map Table can be segmented to occupy multiple sections so that
- * we have to know which sections we have already received (IsKnown() /
- * SetKnown() calls)
- * Note that the processing of those sections is different from the one of the
- * others since here a section refers to a single program, and a program cannot
- * be segmented into multiple sections
- *****************************************************************************/
-static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
-{
-  u16 i_pgrm_number;          /* Id of the program described in that section */
-  u8 i_version;               /* Version of the description for that program */
-
-  u16 i_offset;
-  u16 i_section_length;
-  u16 i_descr_end;
-
-  u8 i_last_section;
-  u8 i_current_section;
-
-  u16 i_es_pid;
-
-  int i_index = 0;
-#ifdef AUTO_SPAWN
-  int i_es_loop;
-#endif
-  pgrm_descriptor_t* p_pgrm;
-  es_descriptor_t* p_es;
-
-#define p_descr (p_input->p_stream)
-
-  /* Read the id of the program described in that section */
-  i_pgrm_number = U16_AT(&p_pms[3]);
-//  intf_DbgMsg( "PMT section received for program %d\n", i_pgrm_number );
-
-  /* Find where is stored the description of this program */
-  for( i_index = 0; i_index < p_descr->i_pgrm_number &&
-       i_pgrm_number != p_descr->ap_programs[i_index]->i_number; i_index++ );
-
-  if( i_index >= p_descr->i_pgrm_number )
-  {
-    /* If none entry exists, this simply means that the PAT is not complete,
-       so skip this section since it is the responsability of the PAT decoder
-       to add pgrm_descriptor slots to the table of known pgrms */
-    intf_DbgMsg( "Unknown pgrm %d: skipping its description\n", i_pgrm_number );
-    return;
-  }
-
-  /* We now have the slot which is the program described: we can begin with
-     the decoding of its description */
-  p_pgrm = p_descr->ap_programs[i_index];
-
-  /* Which section of the description of that program did we receive ? */
-  i_last_section = p_pms[7];
-  i_current_section = p_pms[6];
-//  intf_DbgMsg("Section %d (last section %d)\n", i_current_section, i_last_section);
-
-  /* Is this an update of the description for this program ? */
-  i_version = (p_pms[5] >> 1) & 0x1F;
-    if( p_pgrm->i_version != i_version )
-    {
-        intf_DbgMsg("Updating PMT for program %d\n", i_pgrm_number);
-
-        for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
-        {
-          /* Stop the reception of the ES if needed by calling the function
-             normally used by the interface to manage this */
-          if( input_IsElemRecv(p_input, p_pgrm->ap_es[i_index]->i_id) )
-          {
-            intf_DbgMsg( "PID %d is no more valid: stopping its reception\n",
-                      p_pgrm->ap_es[i_index]->i_id );
-            input_DelPgrmElem( p_input, p_pgrm->ap_es[i_index]->i_id );
-          }
-
-          /* Remove the descriptor associated to the es of this programs */
-          intf_DbgMsg( "Invalidating PID %d\n", p_pgrm->ap_es[i_index]->i_id );
-          DestroyESDescr(p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id);
-        }
-
-       /* Update version number */
-        p_pgrm->i_version = i_version;
-
-        /* Ask the decoder to update the description of that program */
-        p_descr->i_known_PMT_sections--;
-        Unset_known( p_descr->a_known_PMT_sections, i_current_section );
-        p_pgrm->b_is_ok = 0;
-    }
-
-    /* Read the info for that pgrm is the one we have is not up to date or
-       if we don't have any */
-    if( p_pgrm->b_is_ok )
-    {
-      /* Nothing to do */
-//      intf_DbgMsg("Program description OK, nothing to do\n");
-    }
-    else
-    {
-        /* Check if we already heard about that section */
-        if( Is_known(p_descr->a_known_PMT_sections, i_current_section) )
-        {
-          /* Nothing to do */
-//          intf_DbgMsg("Section already received, skipping\n");
-        }
-        else
-        {
-          /* Read the corresponding PCR */
-          p_pgrm->i_pcr_pid = U16_AT(&p_pms[8]) & 0x1fff;
-          intf_DbgMsg("PCR at PID: %d\n", p_pgrm->i_pcr_pid);
-
-          /* Compute the length of the section minus the final CRC */
-          i_section_length = (U16_AT(&p_pms[1]) & 0xfff) + 3 - 4;
-          intf_DbgMsg("Section length (without CRC): %d\n", i_section_length);
-
-          /* Read additional info stored in the descriptors if any */
-          intf_DbgMsg("Description length for program %d: %d\n",
-                      p_pgrm->i_number, (U16_AT(&p_pms[10]) & 0x0fff));
-          i_descr_end = (U16_AT(&p_pms[10]) & 0x0fff) + 12;
-          intf_DbgMsg("description ends at offset: %d\n",  i_descr_end);
-
-          i_offset = 12;
-          while( i_offset < i_descr_end )
-          {
-            DecodePgrmDescriptor(&p_pms[i_offset], p_pgrm);
-            i_offset += p_pms[i_offset+1] + 2;
-          }
-
-          /* Read all the ES descriptions */
-          while( i_offset < i_section_length )
-          {
-            /* Read type of that ES */
-            intf_DbgMsg("ES Type: %d\n", p_pms[i_offset]);
-
-            /* Read PID of that ES */
-            i_es_pid = U16_AT(&p_pms[i_offset+1]) & 0x1fff;
-            intf_DbgMsg("ES PID: %d\n", i_es_pid);
-
-            /* Add the ES to the program description and reserve a slot in the
-               table of ES to store its description */
-            p_es = AddESDescr(p_input, p_pgrm, i_es_pid);
-            if (!p_es)
-            {
-              intf_ErrMsg("Warning: definition for pgrm %d won't be complete\n",
-                          p_pgrm->i_number);
-              /* The best way to handle this is to stop decoding the info for
-                 that section but do as if everything is ok. Thus we will
-                 eventually have an uncomplete ES table marked as being
-                 complete and some error msgs */
-              break;
-            }
-            else
-            {
-              /* Store the description of that PID in the slot */
-              p_es->i_type = p_pms[i_offset];
-              p_es->b_psi = 0;
-              if( i_es_pid == p_pgrm->i_pcr_pid )
-                p_es->b_pcr = 1;
-              else
-                p_es->b_pcr = 0;
-
-              /* Read additional info given by the descriptors */
-              i_offset += 5;
-              intf_DbgMsg("description length for PID %d: %d\n", p_es->i_id,
-                       (U16_AT(&p_pms[i_offset-2]) & 0x0fff));
-              i_descr_end = (U16_AT(&p_pms[i_offset-2]) & 0x0fff) + i_offset;
-              intf_DbgMsg("description ends at offset: %d\n",  i_descr_end);
-              while( i_offset < i_descr_end )
-              {
-                DecodeESDescriptor(&p_pms[i_offset], p_es);
-                i_offset += p_pms[i_offset+1] + 2;
-              }
-            }
-
-            /* Jump to next ES description */
-          }
-
-          /* We now know the info carried in this section */
-          intf_DbgMsg("Description of program %d complete\n", p_pgrm->i_number);
-          p_pgrm->b_is_ok = 1;
-          Set_known(p_descr->a_known_PMT_sections, i_current_section);
-
-          /* Check if the PMT is now complete */
-          p_descr->i_known_PMT_sections++;
-          if( p_descr->i_known_PMT_sections >= i_last_section)
-          {
-              p_descr->b_is_PMT_complete = 1;
-
-#ifdef AUTO_SPAWN
-              /* Spawn an audio and a video thread, if possible. */
-              for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
-              {
-                  switch( p_input->p_es[i_es_loop].i_type )
-                  {
-                      case MPEG1_VIDEO_ES:
-                      case MPEG2_VIDEO_ES:
-                          if( p_main->b_video )
-                          {
-                              /* Spawn a video thread */
-                              input_AddPgrmElem( p_input,
-                                  p_input->p_es[i_es_loop].i_id );
-                          }
-                          break;
-
-                      case AC3_AUDIO_ES:
-                          if ( p_main->b_audio )
-                          {
-                              /* Spawn an ac3 thread */
-                              input_AddPgrmElem( p_input,
-                                  p_input->p_es[i_es_loop].i_id );
-                              }
-                          break;
-
-                      case LPCM_AUDIO_ES:
-                          if ( p_main->b_audio )
-                          {
-                              /* Spawn an lpcm thread */
-                              input_AddPgrmElem( p_input,
-                                  p_input->p_es[i_es_loop].i_id );
-                              }
-                          break;
-
-                     case DVD_SPU_ES:
-                          if ( p_main->b_video )
-                          {
-                              /* Spawn a spu decoder thread */
-                              input_AddPgrmElem( p_input,
-                                  p_input->p_es[i_es_loop].i_id );
-                              }
-                          break;
-
-                      case MPEG1_AUDIO_ES:
-                      case MPEG2_AUDIO_ES:
-                          if( p_main->b_audio )
-                          {
-                              /* Spawn an audio thread */
-                              input_AddPgrmElem( p_input,
-                                  p_input->p_es[i_es_loop].i_id );
-                          }
-                          break;
-
-                      default:
-                          break;
-                  }
-              }
-#endif
-          }
-        }
-    }
-
-#undef p_descr
-}
-
-/*****************************************************************************
- * DecodeSrvDescrSection
- *****************************************************************************
- * FIXME: A finir et a refaire proprement ??
- *****************************************************************************/
-void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input )
-{
-  u16 i_stream_id;
-  u8 i_version;
-  u16 i_length;
-
-  int i_index;
-  int i_offset;
-  boolean_t b_must_update = 0;
-
-  int i_descr_end;
-
-  ASSERT(p_sdt);
-  ASSERT(p_input);
-
-#define p_stream (p_input->p_stream)
-
-   /* Read stream id and version number immediately, to be sure they will be
-      initialised in all the cases in which we will need them */
-   i_stream_id = U16_AT(&p_sdt[3]);
-   i_version = (p_sdt[5] >> 1) & 0x1F;
-   intf_DbgMsg("TS Id: %d, version: %d\n", i_stream_id, i_version);
-
-   /* Take the descriptor into account only if it describes the streams we are
-      receiving */
-   if( p_stream->i_stream_id != i_stream_id )
-   {
-     intf_DbgMsg("SDT doen't apply to our TS but to %s: aborting\n",
-                  U16_AT(&p_sdt[3]));
-   }
-   else
-   {
-     /* Section applyies to our TS, test if the SDT is up to date */
-     if( p_stream->i_SDT_version != i_version )
-     {
-       intf_DbgMsg("SDT has been updated, NOT YET IMPLEMENTED\n");
-
-       /* Ask the PSI decoder to rebuild the table */
-        b_must_update = 1;
-     }
-   }
-
-   /* Rebuild the table if needed */
-   if( b_must_update )
-   {
-     intf_DbgMsg("Updating SDT table\n");
-
-     i_length = p_sdt[1] & 0x0FFF;
-     i_offset = 11;
-
-     while(i_offset < i_length)
-     {
-
-       /* Find the program to which the description applies */
-       for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
-       {
-         if( p_stream->ap_programs[i_index]->i_number ==
-             U16_AT(&p_sdt[i_offset]) )
-         {
-           /* Here we are */
-           intf_DbgMsg("FOUND: %d\n", p_stream->ap_programs[i_index]->i_number);
-           break;
-         }
-       }
-
-       /* Copy the info to the description of that program */
-       i_offset += 5;
-       intf_DbgMsg("description length for SDT: %d\n",
-                   (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF));
-       i_descr_end = (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF) + i_offset;
-       intf_DbgMsg("description ends at offset: %d\n",  i_descr_end);
-       while( i_offset < i_descr_end )
-       {
-         DecodePgrmDescriptor(&p_sdt[i_offset], p_stream->ap_programs[i_index]);
-         i_offset += p_sdt[i_offset+1] + 2;
-       }
-     }
-   }
-#undef p_stream
-}
-
-/*****************************************************************************
- * DecodePgrmDescr
- *****************************************************************************
- * Decode any descriptor applying to the definition of a program
- *****************************************************************************/
-static void DecodePgrmDescriptor( byte_t* p_descriptor,
-                                  pgrm_descriptor_t* p_pgrm )
-{
-    u8 i_type;                                     /* Type of the descriptor */
-    u8 i_length;                                 /* Length of the descriptor */
-#ifdef DVB_EXTENSIONS
-    int i_offset;                      /* Current position in the descriptor */
-#endif
-
-    ASSERT(p_descriptor);
-    ASSERT(p_pgrm);
-
-    /* Read type and length of the descriptor */
-    i_type = p_descriptor[0];
-    i_length = p_descriptor[1];
-
-    /* Handle specific descriptor info */
-    switch(i_type)
-    {
-#ifdef DVB_EXTENSIONS
-    case PSI_SERVICE_DESCRIPTOR:
-    {
-        /* Store service type */
-        p_pgrm->i_srv_type = p_descriptor[2];
-
-        /* Jump to the beginning of the service name */
-        i_offset = p_descriptor[3] + 5;
-
-        /* Check that the charset used is the normal one (latin) by testing the
-           first byte of the name */
-        if( p_descriptor[i_offset] >= 0x20 )
-        {
-            /* The charset is the one of our computer: just dup the string */
-            p_pgrm->psz_srv_name = malloc(i_length - i_offset +1);
-            memcpy(p_pgrm->psz_srv_name, &p_descriptor[i_offset],
-                   i_length - i_offset);
-            p_pgrm->psz_srv_name[i_length - i_offset + 1] = '\0';
-        }
-        else
-        {
-            /* Indicate that the name couldn't be printed */
-            p_pgrm->psz_srv_name = "Ununderstandable :)";
-        }
-        break;
-    }
-#endif
-    default:
-//        intf_DbgMsg("Unhandled program descriptor received (type: %d)\n", i_type);
-//        intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
-    }
-}
-
-/*****************************************************************************
- * DecodeESDescriptor
- *****************************************************************************
- * Decode any descriptor applying to the definition of an ES
- *****************************************************************************/
-static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es )
-{
-    u8 i_type;                                     /* Type of the descriptor */
-    u8 i_length;                                 /* Length of the descriptor */
-//    int i_offset;                    /* Current position in the descriptor */
-
-    ASSERT(p_descriptor);
-    ASSERT(p_es);
-
-    /* Read type and length of the descriptor */
-    i_type = p_descriptor[0];
-    i_length = p_descriptor[1];
-
-    switch( i_type )
-    {
-    case PSI_VIDEO_STREAM_DESCRIPTOR:
-    {
-        intf_DbgMsg("Video stream descriptor received\n");
-        break;
-    }
-    case PSI_AUDIO_STREAM_DESCRIPTOR:
-    {
-        intf_DbgMsg("Audio stream descriptor received\n");
-        break;
-    }
-    case PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR:
-    {
-        intf_DbgMsg("Target background descriptor received\n");
-        break;
-    }
-    case PSI_VIDEO_WINDOW_DESCRIPTOR:
-    {
-        intf_DbgMsg("Video window descriptor received\n");
-        break;
-    }
-    default:
-//        intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
-//        intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
-    }
-}
-
-/*****************************************************************************
- * input_AddPsiPID: Start to receive the PSI info contained in a PID
- *****************************************************************************
- * Add a descriptor to the table of es descriptor for that es and mark the es
- * as being to be received by the input (since all PSI must be received to
- * build the description of the program)
- *****************************************************************************/
-static int input_AddPsiPID( input_thread_t *p_input, int i_pid )
-{
-  int i_index;
-  es_descriptor_t* p_psi_es;
-  int i_rc = 0;
-
-  /* Store the description of this stream in the input thread */
-  p_psi_es = AddESDescr(p_input, NULL, i_pid);
-
-  if(p_psi_es)
-  {
-    /* Precise this ES carries PSI */
-    p_psi_es->b_psi = 1;
-
-    /* Create the buffer needed by the PSI decoder */
-    p_psi_es->p_psi_section = malloc( sizeof( psi_section_t) );
-    if( !p_psi_es->p_psi_section )
-    {
-      intf_ErrMsg( "Malloc error\n" );
-      i_rc = -1;
-    }
-    else
-    {
-      /* Init the reception for that PID */
-      p_psi_es->p_psi_section->b_running_section = 0;
-//      p_psi_es->p_psi_section->b_discard_payload = 0;
-
-      /* Ask the input thread to demultiplex it: since the interface
-         can also access the table of selected es, lock the elementary
-         stream structure */
-      vlc_mutex_lock( &p_input->es_lock );
-      for( i_index = 0; i_index < INPUT_MAX_SELECTED_ES; i_index++ )
-      {
-        if( !p_input->pp_selected_es[i_index] )
-        {
-          intf_DbgMsg( "Free Selected ES slot found at offset %d for PID %d\n",
-                       i_index, i_pid );
-          p_input->pp_selected_es[i_index] = p_psi_es;
-          break;
-        }
-      }
-      vlc_mutex_unlock( &p_input->es_lock );
-
-      if( i_index >= INPUT_MAX_SELECTED_ES )
-      {
-        intf_ErrMsg( "Stream carries to many PID for our decoder\n" );
-        i_rc = -1;
-      }
-    }
-  }
-
-  return( i_rc );
-}
-
-/*****************************************************************************
- * input_DelPsiPID: Stop to receive the PSI info contained in a PID
- *****************************************************************************
- * Remove the PID from the list of ES descriptors and from the list of ES that
- * the input must receive.
- * Known PID for PSI should always be received, so that their description
- * should be pointed out by a member of pp_selected_es. But as INPUT_MAX_ES
- * can be different of INPUT_MAX_SELECTED_ES, this may happen, so that we must
- * do 2 loops.
- *****************************************************************************/
-static int input_DelPsiPID( input_thread_t *p_input, int i_pid )
-{
-  int i_es_index, i_last_sel;
-
-  intf_DbgMsg( "Deleting PSI PID %d\n", i_pid );
-
-  /* Stop to receive the ES. Since the interface can also access the table
-     of selected es, lock the elementary stream structure */
-  vlc_mutex_lock( &p_input->es_lock );
-
-  for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES; i_es_index++ )
-  {
-    if( p_input->pp_selected_es[i_es_index] &&
-        p_input->pp_selected_es[i_es_index]->i_id == i_pid )
-    {
-      /* Unmark the stream */
-      p_input->pp_selected_es[i_es_index] = NULL;
-
-      /* There must not be any gap in the pp_selected_es, so move the last
-         selected stream to this slot */
-      for( i_last_sel = i_es_index; p_input->pp_selected_es[i_last_sel] &&
-            i_last_sel < INPUT_MAX_SELECTED_ES; i_last_sel++ );
-      p_input->pp_selected_es[i_es_index] = p_input->pp_selected_es[i_last_sel];
-      p_input->pp_selected_es[i_last_sel] = NULL;
-      break;
-    }
-  }
-
-  vlc_mutex_unlock( &p_input->es_lock );
-
-#ifdef DEBUG
-  /* Check if the pp_selected_es table may be corrupted */
-  if( i_es_index >= INPUT_MAX_PROGRAM_ES )
-  {
-    intf_ErrMsg( "DelPsiPID error: PID %d is not currently received\n", i_pid );
-  }
-#endif
-
-  /* Remove the desription of that ES from the table of ES */
-  DestroyESDescr(p_input, NULL, i_pid);
-
-  return( 0 );
-}
-
-/*****************************************************************************
- * Precalculate the 32-bit CRC table
- *****************************************************************************
- * This table is a global variable shared by all decoders, so it has to be
- * initialised only once
- *****************************************************************************/
-void BuildCrc32Table( )
-{
-    u32 i, j, k;
-    for( i = 0 ; i < 256 ; i++ )
-    {
-        k = 0;
-        for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1)
-            k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
-        i_crc_32_table[i] = k;
-    }
-}
-
-/*****************************************************************************
- * Test the validity of a checksum
- *****************************************************************************
- * The checksum must be stored at the end of the data, and the given size must
- * include the 32 bits of the CRC.
- * Return 0 if the checksum is OK, any other value if the data are corrupted
- *****************************************************************************/
-int CheckCRC32(byte_t* p_data, int i_data_size)
-{
-  int i;
-  u32 i_crc = 0xffffffff;
-
-  ASSERT(p_data);
-
-  for (i = 0; i < i_data_size; i++)
-    i_crc = (i_crc << 8) ^ i_crc_32_table[(i_crc >> 24) ^ p_data[i]];
-
-  return i_crc;
-}
-
-/*****************************************************************************
- * Is_known: check if a given section has already been received
- *****************************************************************************
- * As a table cannot be segmented into more than 256 sections, we store a 256
- * bits long table, each bit set to one indicating that the corresponding
- * saction has been received
- *****************************************************************************/
-boolean_t Is_known( byte_t* a_known_section, u8 i_section )
-{
-  byte_t mask;
-  boolean_t b_is_known;
-
-  /* Where to get the information ? */
-  int i_bit_in_byte = i_section % 8;
-  int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
-
-  /* Build mask to read the Is_known flag */
-  mask = 0x01 << i_bit_in_byte;
-
-  /* Read the flag */
-  b_is_known = a_known_section[i_byte_in_table] & mask;
-
-  return b_is_known;
-}
-
-/*****************************************************************************
- * Set_known: mark a given section has having been received
- *****************************************************************************
- *
- *****************************************************************************/
-static void Set_known( byte_t* a_known_section, u8 i_section )
-{
-  byte_t mask;
-
-  /* Where to get the information ? */
-  int i_bit_in_byte = i_section % 8;
-  int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
-
-  /* Build mask to read the Is_known flag */
-  mask = 0x01 << i_bit_in_byte;
-
-  /* Set the flag */
-  a_known_section[i_byte_in_table] |= mask;
-}
-
-/*****************************************************************************
- * Unset_known: remove the 'received' mark for a given section
- *****************************************************************************
- *
- *****************************************************************************/
-static void Unset_known( byte_t* a_known_section, u8 i_section )
-{
-  byte_t mask;
-
-  /* Where to get the information ? */
-  int i_bit_in_byte = i_section % 8;
-  int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
-
-  /* Build mask to read the Is_known flag */
-  mask = 0x01 << i_bit_in_byte;
-  mask = ~mask;
-
-  /* Unset the flag */
-  a_known_section[i_byte_in_table] &= mask;
-}
-
-/*****************************************************************************
- * AddStreamDescr: add and init the stream descriptor of the given input
- *****************************************************************************
- *
- *****************************************************************************/
-static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input,
-                                           u16 i_stream_id)
-{
-  ASSERT(p_input);
-
-  intf_DbgMsg("Adding description for stream %d\n", i_stream_id);
-
-  p_input->p_stream = malloc( sizeof(stream_descriptor_t) );
-
-  p_input->p_stream->i_stream_id = i_stream_id;
-
-  p_input->p_stream->i_PAT_version = PSI_UNINITIALISED;
-  p_input->p_stream->i_known_PAT_sections = 0;
-  memset( p_input->p_stream->a_known_PAT_sections, 0,
-          sizeof(*p_input->p_stream->a_known_PAT_sections) );
-  p_input->p_stream->b_is_PAT_complete = 0;
-
-  p_input->p_stream->i_known_PMT_sections = 0;
-  memset( p_input->p_stream->a_known_PMT_sections, 0,
-          sizeof(*p_input->p_stream->a_known_PMT_sections) );
-  p_input->p_stream->b_is_PMT_complete = 0;
-
-#ifdef DVB_EXTENSIONS
-  p_input->p_stream->i_SDT_version = PSI_UNINITIALISED;
-  p_input->p_stream->i_known_SDT_sections = 0;
-  memset( p_input->p_stream->a_known_SDT_sections, 0,
-         sizeof(*p_input->p_stream->a_known_SDT_sections) );
-  p_input->p_stream->b_is_SDT_complete = 0;
-#endif
-
-  p_input->p_stream->i_pgrm_number = 0;
-  p_input->p_stream->ap_programs = NULL;
-
-  return p_input->p_stream;
-}
-
-/*****************************************************************************
- * DestroyStreamDescr: destroy the stream desciptor of the given input
- *****************************************************************************
- *
- *****************************************************************************/
-static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id)
-{
-  int i_index;
-
-  ASSERT(p_input);
-
-  /* Free the structures that describes the programs of that stream */
-  for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
-  {
-    DestroyPgrmDescr( p_input, p_input->p_stream,
-                      p_input->p_stream->ap_programs[i_index]->i_number );
-  }
-
-  /* Free the table of pgrm descriptors */
-  free( p_input->p_stream->ap_programs );
-
-  /* Free the structure that describes the stream itself */
-  free( p_input->p_stream );
-
-  /* Input thread has no more stream descriptor */
-  p_input->p_stream = NULL;
-}
-
-/*****************************************************************************
- * AddPgrmDescr: add and init a program descriptor
- *****************************************************************************
- * This program descriptor will be referenced in the given stream descriptor
- *****************************************************************************/
-static pgrm_descriptor_t* AddPgrmDescr( stream_descriptor_t* p_stream,
-                                        u16 i_pgrm_id)
-{
-  int i_pgrm_index = p_stream->i_pgrm_number;       /* Where to add the pgrm */
-
-  ASSERT(p_stream);
-
-  intf_DbgMsg("Adding description for pgrm %d\n", i_pgrm_id);
-
-  /* Add an entry to the list of program associated with the stream */
-  p_stream->i_pgrm_number++;
-  p_stream->ap_programs = realloc( p_stream->ap_programs,
-                          p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t*) );
-
-  /* Allocate the structure to store this description */
-  p_stream->ap_programs[i_pgrm_index] = malloc(sizeof(pgrm_descriptor_t));
-
-  /* Init this entry */
-  p_stream->ap_programs[i_pgrm_index]->i_number = i_pgrm_id;
-  p_stream->ap_programs[i_pgrm_index]->i_version = PSI_UNINITIALISED;
-  p_stream->ap_programs[i_pgrm_index]->b_is_ok = 0;
-
-  p_stream->ap_programs[i_pgrm_index]->i_es_number = 0;
-  p_stream->ap_programs[i_pgrm_index]->ap_es = NULL;
-
-  /* descriptors ? XXX?? */
-
-  return p_stream->ap_programs[i_pgrm_index];
-}
-
-/*****************************************************************************
- * AddPgrmDescr: destroy a program descriptor
- *****************************************************************************
- * All ES descriptions referenced in the descriptor will be deleted.
- *****************************************************************************/
-static void DestroyPgrmDescr( input_thread_t * p_input,
-                              stream_descriptor_t * p_stream, u16 i_pgrm_id )
-{
-  int i_index, i_pgrm_index = -1;
-  pgrm_descriptor_t* p_pgrm = NULL;
-
-  ASSERT( p_stream );
-
-  intf_DbgMsg("Deleting description for pgrm %d\n", i_pgrm_id);
-
-  /* Find where this program is described */
-  for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
-  {
-    if( p_stream->ap_programs[i_index]->i_number == i_pgrm_id )
-    {
-      i_pgrm_index = i_index;
-      p_pgrm = p_stream->ap_programs[ i_pgrm_index ];
-      break;
-    }
-  }
-
-  /* Make sure that the pgrm exists */
-  ASSERT(i_pgrm_index >= 0);
-  ASSERT(p_pgrm);
-
-  /* Free the structures that describe the es that belongs to that program */
-  for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
-  {
-    DestroyESDescr( p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id );
-  }
-
-  /* Free the table of es descriptors */
-  free( p_pgrm->ap_es );
-
-  /* Free the description of this stream */
-  free( p_pgrm );
-
-  /* Remove this program from the stream's list of programs */
-  p_stream->i_pgrm_number--;
-  p_stream->ap_programs[i_pgrm_index] =
-                                 p_stream->ap_programs[p_stream->i_pgrm_number];
-  p_stream->ap_programs = realloc( p_stream->ap_programs,
-                          p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t *) );
-}
-
-/*****************************************************************************
- * AddESDescr:
- *****************************************************************************
- * Reserve a slot in the table of ES descritors for the ES and add it to the
- * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
- * alone (PSI ?)
- *****************************************************************************/
-static es_descriptor_t* AddESDescr(input_thread_t* p_input,
-                                   pgrm_descriptor_t* p_pgrm, u16 i_es_pid)
-{
-  int i_index;
-  es_descriptor_t* p_es = NULL;
-
-  ASSERT(p_input);
-
-  intf_DbgMsg("Adding description for ES %d\n", i_es_pid);
-
-  /* Find an empty slot to store the description of that es */
-  for( i_index = 0; i_index < INPUT_MAX_ES &&
-        p_input->p_es[i_index].i_id != EMPTY_PID; i_index++ );
-
-  if( i_index >= INPUT_MAX_ES )
-  {
-    /* No slot is empty */
-    intf_ErrMsg("Stream carries to many PID for our decoder\n");
-  }
-  else
-  {
-    /* Reserve the slot for that ES */
-    p_es = &p_input->p_es[i_index];
-    p_es->i_id = i_es_pid;
-    intf_DbgMsg("Slot %d in p_es table assigned to ES %d\n", i_index, i_es_pid);
-
-    /* Init its values */
-    p_es->i_type = 0;  /* XXX?? */
-    p_es->b_psi = 0;
-    p_es->b_pcr = 0;
-    p_es->i_continuity_counter = 0xFF;
-
-    p_es->p_pes_packet = NULL;
-//    p_es->p_next_pes_packet = NULL;
-    p_es->p_dec = NULL;
-
-    /* Add this ES to the program definition if one is given */
-    if( p_pgrm )
-    {
-      p_pgrm->i_es_number++;
-      p_pgrm->ap_es = realloc( p_pgrm->ap_es,
-                               p_pgrm->i_es_number*sizeof(es_descriptor_t *) );
-      p_pgrm->ap_es[p_pgrm->i_es_number-1] = p_es;
-      intf_DbgMsg( "Added ES %d to definition of pgrm %d\n",
-                   i_es_pid, p_pgrm->i_number );
-    }
-    else
-      intf_DbgMsg( "Added ES %d not added to the definition of any pgrm\n",
-                   i_es_pid );
-  }
-
-  return p_es;
-}
-
-/*****************************************************************************
- * DestroyESDescr:
- *****************************************************************************
- *
- *****************************************************************************/
-static void DestroyESDescr(input_thread_t* p_input,
-                           pgrm_descriptor_t* p_pgrm, u16 i_pid)
-{
-  int i_index;
-
-  /* Look for the description of the ES */
-  for(i_index = 0; i_index < INPUT_MAX_ES; i_index++)
-  {
-    if( p_input->p_es[i_index].i_id == i_pid )
-    {
-      /* The table of stream descriptors is static, so don't free memory
-         but just mark the slot as unused */
-      p_input->p_es[i_index].i_id = EMPTY_PID;
-      break;
-    }
-  }
-
-  /* Remove this ES from the description of the program if it is associated to
-     one */
-  if( p_pgrm )
-  {
-    for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
-    {
-      if( p_input->p_es[i_index].i_id == i_pid )
-      {
-        p_pgrm->i_es_number--;
-        p_pgrm->ap_es[i_index] = p_pgrm->ap_es[p_pgrm->i_es_number];
-        p_pgrm->ap_es = realloc(p_pgrm->ap_es, p_pgrm->i_es_number);
-        break;
-      }
-    }
-  }
-}
diff --git a/src/input/input_psi.h b/src/input/input_psi.h
deleted file mode 100644 (file)
index 885ff7c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * psi.h: PSI management interface
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Benoît Steiner <benny@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-int     input_PsiInit   ( input_thread_t *p_input );
-void    input_PsiDecode ( input_thread_t *p_input, psi_section_t* p_psi_section );
-void    input_PsiRead   ( input_thread_t *p_input );
-int     input_PsiEnd    ( input_thread_t *p_input );
similarity index 52%
rename from include/input_vlan.h
rename to src/input/input_ts.c
index ec2767f897f49d30198ce4dc6bb5be4b70a924c5..19cf57fe7fcffffbc69dbeee1cf80ab63c227e4d 100644 (file)
@@ -1,9 +1,9 @@
 /*****************************************************************************
- * input_vlan.h: vlan input method
+ * input_ts.c: TS demux and netlist management
  *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
+ * Copyright (C) 1998, 1999, 2000 VideoLAN
  *
- * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ * 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
  *****************************************************************************/
 
 /*****************************************************************************
- * Required headers:
- * <netinet/in.h>
- * "threads.h"
+ * Preamble
  *****************************************************************************/
+#include "time_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
 
 /*****************************************************************************
- * Prototypes
+ * Local prototypes
  *****************************************************************************/
-int     input_VlanCreate        ( void );
-void    input_VlanDestroy       ( void );
-int     input_VlanJoin          ( int i_vlan_id );
-void    input_VlanLeave         ( int i_vlan_id );
-
+static int  TSProbe     ( struct input_thread_s * );
+static void TSRead      ( struct input_thread_s * );
+static int  TSInit      ( struct input_thread_s * );
+static void TSEnd       ( struct input_thread_s * );
+static struct data_packet_s * NewPacket ( struct input_thread_s *,
+                                          size_t );
+static void DeletePacket( struct input_thread_s *,
+                          struct data_packet_s * );
+static void DeletePES   ( struct input_thread_s *,
+                          struct pes_packet_s * );
 
+/*****************************************************************************
+ * TSProbe: verifies that the stream is a TS stream
+ *****************************************************************************/
+static int TSProbe( input_thread_t * p_input )
+{
+    /* verify that the first byte is 0x47 */
+}
 
+static void TSInit( input_thread_t * p_input )
+{
+    /* Initialize netlist and TS structures */
+}
diff --git a/src/input/input_ts.h b/src/input/input_ts.h
new file mode 100644 (file)
index 0000000..ce2aa54
--- /dev/null
@@ -0,0 +1,17 @@
+/*****************************************************************************
+ * thread_ts_data_t: extension of input_thread_t
+ *****************************************************************************/
+typedef struct thread_ts_data_s
+{
+    /* To use the efficiency of the scatter/gather IO operations without
+     * malloc'ing all the time, we implemented a FIFO of free data packets.
+     */
+    vlc_mutex_lock          lock;
+    struct iovec            p_free_iovec[INPUT_MAX_TS + INPUT_TS_READ_ONCE];
+    data_packet_t *         p_free_ts[INPUT_MAX_TS + INPUT_TS_READ_ONCE];
+    int                     i_free_start, i_free_end;
+
+    /* The free data packets are stored here : */
+    data_packet_t *         p_data_packets;
+    byte_t *                p_buffers;
+} thread_ts_data_t;
diff --git a/src/input/input_vlan.c b/src/input/input_vlan.c
deleted file mode 100644 (file)
index 52fa1d6..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*****************************************************************************
- * input_vlan.c: vlan management library
- *****************************************************************************
- * Copyright (C) 1999, 2000 VideoLAN
- *
- * Authors: Vincent Seguin <seguin@via.ecp.fr>
- *
- * 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 <errno.h>                                                 /* ENOMEM */
-#include <stdio.h>                                              /* sprintf() */
-#include <unistd.h>                                               /* close() */
-#include <string.h>                                   /* strerror(), bzero() */
-#include <stdlib.h>                                                /* free() */
-#include <sys/time.h>                             /* timeval */
-
-#if defined(SYS_BSD) || defined(SYS_BEOS)
-#include <netinet/in.h>                                    /* struct in_addr */
-#include <sys/socket.h>                                   /* struct sockaddr */
-#endif
-
-#if defined(SYS_LINUX) || defined(SYS_BSD) || defined(SYS_GNU)
-#include <arpa/inet.h>                           /* inet_ntoa(), inet_aton() */
-#endif
-
-#ifdef SYS_LINUX
-#include <sys/ioctl.h>                                            /* ioctl() */
-#include <net/if.h>                            /* interface (arch-dependent) */
-#endif
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-#include "plugins.h"
-#include "netutils.h"
-#include "input_vlan.h"
-#include "intf_msg.h"
-
-#include "main.h"
-
-/*****************************************************************************
- * input_vlan_t: vlan library data
- *****************************************************************************
- * Store global vlan library data.
- *****************************************************************************/
-typedef struct input_vlan_s
-{
-    int         i_vlan_id;                            /* current vlan number */
-    mtime_t     last_change;                             /* last change date */
-} input_vlan_t;
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-
-/*****************************************************************************
- * input_VlanCreate: initialize global vlan method data
- *****************************************************************************
- * Initialize vlan input method global data. This function should be called
- * once before any input thread is created or any call to other input_Vlan*()
- * function is attempted.
- *****************************************************************************/
-int input_VlanCreate( void )
-{
-#ifdef SYS_BEOS
-    intf_ErrMsg( "error: vlans are not supported under beos\n" );
-    return( 1 );
-#else
-    /* Allocate structure */
-    p_main->p_vlan = malloc( sizeof( input_vlan_t ) );
-    if( p_main->p_vlan == NULL )
-    {
-        intf_ErrMsg("error: %s\n", strerror(ENOMEM));
-        return( 1 );
-    }
-
-    /* Initialize structure */
-    p_main->p_vlan->i_vlan_id   = 0;
-    p_main->p_vlan->last_change = 0;
-
-    intf_Msg("VLANs initialized\n");
-    return( 0 );
-#endif /* SYS_BEOS */
-}
-
-/*****************************************************************************
- * input_VlanDestroy: free global vlan method data
- *****************************************************************************
- * Free resources allocated by input_VlanMethodInit. This function should be
- * called at the end of the program.
- *****************************************************************************/
-void input_VlanDestroy( void )
-{
-    /* Return to default vlan */
-    if( p_main->p_vlan->i_vlan_id != 0 )
-    {
-        input_VlanJoin( 0 );
-    }
-
-    /* Free structure */
-    free( p_main->p_vlan );
-}
-
-/*****************************************************************************
- * input_VlanLeave: leave a vlan
- *****************************************************************************
- * This function tells the vlan library that the designed interface is no more
- * locked and than vlan changes can occur.
- *****************************************************************************/
-void input_VlanLeave( int i_vlan_id )
-{
-    /* XXX?? */
-}
-
-/*****************************************************************************
- * input_VlanJoin: join a vlan
- *****************************************************************************
- * This function will try to join a vlan. If the relevant interface is already
- * on the good vlan, nothing will be done. Else, and if possible (if the
- * interface is not locked), the vlan server will be contacted and a change will
- * be requested. The function will block until the change is effective. Note
- * that once a vlan is no more used, it's interface should be unlocked using
- * input_VlanLeave().
- * Non 0 will be returned in case of error.
- *****************************************************************************/
-int input_VlanJoin( int i_vlan_id )
-{
-#ifdef SYS_BEOS
-    return( -1 );
-#else
-
-#define SERVER "138.195.130.90"
-#define INTERFACE "eth0"
-/* default server port */
-#define VLANSERVER_PORT 6010
-    
-    int                 socket_cl;
-    int                 fromlen;
-    struct ifreq        interface;
-    struct sockaddr_in  sa_server;
-    struct sockaddr_in  sa_client;
-    unsigned int        version = 12;
-    char                mess[80];
-    struct timeval     *date_cl;
-    struct timeval      time;
-    long unsigned int   date;
-    int                 nbanswer;
-    char                answer;
-    fd_set              rfds;
-
-    /* If last change is too recent, wait a while */
-    if( mdate() - p_main->p_vlan->last_change < INPUT_VLAN_CHANGE_DELAY )
-    {
-        intf_Msg("Waiting before changing VLAN...\n");
-        mwait( p_main->p_vlan->last_change + INPUT_VLAN_CHANGE_DELAY );
-    }
-    p_main->p_vlan->last_change = mdate();
-    p_main->p_vlan->i_vlan_id = i_vlan_id;
-
-    intf_Msg("Joining VLAN %d (channel %d)\n", i_vlan_id + 2, i_vlan_id );
-
-    /*      
-     *Looking for informations about the eth0 interface
-     */
-    interface.ifr_addr.sa_family = AF_INET;
-    strcpy( interface.ifr_name, INTERFACE );
-    
-    
-    /*
-     * Initialysing the socket
-     */
-    socket_cl = socket( AF_INET, SOCK_DGRAM, 0 );
-    intf_DbgMsg( "socket %d\n", socket_cl );
-
-    
-    /* 
-     * Getting the server's information 
-     */
-    bzero (&sa_server, sizeof (struct sockaddr_in));
-    sa_server.sin_family = AF_INET;
-    sa_server.sin_port = htons (VLANSERVER_PORT);
-    inet_aton (SERVER, &(sa_server.sin_addr));
-    
-    /*
-     * Looking for the interface MAC address
-     */
-    ioctl( socket_cl, SIOCGIFHWADDR, &interface );
-    intf_DbgMsg( "macaddr == %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
-        interface.ifr_hwaddr.sa_data[0] & 0xff,
-        interface.ifr_hwaddr.sa_data[1] & 0xff,
-        interface.ifr_hwaddr.sa_data[2] & 0xff,
-        interface.ifr_hwaddr.sa_data[3] & 0xff,
-        interface.ifr_hwaddr.sa_data[4] & 0xff,
-        interface.ifr_hwaddr.sa_data[5] & 0xff );
-    
-    /*
-     * Getting date of the client
-     */
-    date_cl = malloc (sizeof (struct timeval));
-    if (gettimeofday (date_cl, 0) == -1)
-    {
-        return -1;
-    }
-    date = date_cl->tv_sec;
-    intf_DbgMsg ("date %lu\n", date);
-
-
-    /* 
-     * Build of the message
-     */
-    sprintf (mess, "%d %u %lu %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n",
-        i_vlan_id, version, date,
-    interface.ifr_hwaddr.sa_data[0] & 0xff, 
-    interface.ifr_hwaddr.sa_data[1] & 0xff,
-    interface.ifr_hwaddr.sa_data[2] & 0xff,
-    interface.ifr_hwaddr.sa_data[3] & 0xff,
-    interface.ifr_hwaddr.sa_data[4] & 0xff,
-    interface.ifr_hwaddr.sa_data[5] & 0xff);
-    intf_DbgMsg ("The message is %s\n", mess);
-
-
-    /*
-     * Open the socket 2
-     */
-    bzero (&sa_client, sizeof (struct sockaddr_in));
-    sa_client.sin_family = AF_INET;
-    sa_client.sin_port = htons( 4312 );
-    sa_client.sin_addr.s_addr = INADDR_ANY;
-    intf_DbgMsg ("socket %d\n", socket_cl = socket( AF_INET, SOCK_DGRAM, 0 ));
-    fromlen = sizeof (struct sockaddr);
-    intf_DbgMsg( "bind %i\n", bind( socket_cl, (struct sockaddr *)(&sa_client), sizeof( struct sockaddr )));
-
-
-    /*
-     * Send the message
-     */
-    sendto (socket_cl, mess, 80, 0, (struct sockaddr *)(&sa_server), sizeof (struct sockaddr ));
-    {
-      unsigned z;
-      printf("BBP\n");
-      z=0;
-      do {z++;} while (mess[z]!=':');
-      do {z++;} while (mess[z]!='e');
-      printf("meuuh %d %d\n",(unsigned)mess[z+3],(unsigned)mess[z+4]);
-    }
-    printf("BBP2\n");
-
-    
-     /*
-     * Waiting 5 sec for one answer from the server
-     */
-    time.tv_sec = 5;
-    time.tv_usec = 0;
-    FD_ZERO( &rfds );
-    FD_SET( socket_cl, &rfds );
-    nbanswer = select( socket_cl + 1, &rfds, NULL, NULL, &time);
-    if( nbanswer == 0 )
-    {
-        intf_DbgMsg( "no answer\n" );
-    }
-    else if( nbanswer == -1 )
-    {
-        intf_DbgMsg( "I couldn't recieve the answer\n" );
-    }
-    else
-    {
-       recvfrom (socket_cl, &answer, sizeof( char ), 0, (struct sockaddr *)(&sa_client), &fromlen);
-        intf_DbgMsg( "the answer : %hhd\n", answer );
-        if( answer == -1 )
-        {
-            intf_DbgMsg( "The server doesn't succed to create the thread\n" );
-        }
-        else if( answer == 0 )
-        {
-            intf_DbgMsg( "The server try to change the channel\n" );
-        }
-        else
-        {
-            intf_DbgMsg( "I don't know what is this answer !\n" );
-        }
-    }
-    
-
-    /*
-     * Close the socket
-     */
-    close( socket_cl);
-
-    return 0;
-#endif
-}
diff --git a/src/input/mpeg_system.c b/src/input/mpeg_system.c
new file mode 100644 (file)
index 0000000..81b47c5
--- /dev/null
@@ -0,0 +1,1019 @@
+/*****************************************************************************
+ * mpeg_system.c: TS, PS and PES management
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000 VideoLAN
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include <stdlib.h>
+#include <netinet/in.h>
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h"
+
+#include "stream_control.h"
+#include "input_ext-intf.h"
+#include "input_ext-dec.h"
+
+#include "input.h"
+
+#include "mpeg_system.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+
+/*
+ * PES Packet management
+ */
+
+/*****************************************************************************
+ * input_DecodePES
+ *****************************************************************************
+ * Put a PES in the decoder's fifo.
+ *****************************************************************************/
+void input_DecodePES( input_thread_t * p_input, es_descriptor_t * p_es )
+{
+#define p_pes (p_es->p_pes)
+
+    /* FIXME: since we don't check the type of the stream anymore, we don't
+     * do the following : p_data->p_payload_start++; for DVD_SPU_ES, and
+     * DVD SPU support is BROKEN ! */
+
+    if( p_es->p_decoder_fifo != NULL )
+    {
+        vlc_mutex_lock( &p_es->p_decoder_fifo->data_lock );
+        if( !DECODER_FIFO_ISFULL( *p_es->p_decoder_fifo ) )
+        {
+            //intf_DbgMsg("Putting %p into fifo %p/%d\n",
+            //            p_pes, p_fifo, p_fifo->i_end);
+            p_es->p_decoder_fifo->buffer[p_es->p_decoder_fifo->i_end] = p_pes;
+            DECODER_FIFO_INCEND( *p_es->p_decoder_fifo );
+
+            /* Warn the decoder that it's got work to do. */
+            vlc_cond_signal( &p_es->p_decoder_fifo->data_wait );
+        }
+        else
+        {
+            /* The FIFO is full !!! This should not happen. */
+            p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
+            intf_ErrMsg( "PES trashed - fifo full ! (%d, %d)",
+                       p_es->i_id, p_es->i_type);
+        }
+        vlc_mutex_unlock( &p_es->p_decoder_fifo->data_lock );
+    }
+    else
+    {
+        intf_ErrMsg("No fifo to receive PES %p (who wrote this damn code ?)",
+                    p_pes);
+        p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
+    }
+    p_pes = NULL;
+
+#undef p_pes
+}
+
+/*****************************************************************************
+ * input_ParsePES
+ *****************************************************************************
+ * Parse a finished PES packet and analyze its header.
+ *****************************************************************************/
+#define PES_HEADER_SIZE     14
+void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
+{
+    data_packet_t * p_header_data;
+    byte_t          p_header[PES_HEADER_SIZE];
+    int             i_done, i_todo;
+
+#define p_pes (p_es->p_pes)
+
+    //intf_DbgMsg("End of PES packet %p\n", p_pes);
+
+    /* Parse the header. The header has a variable length, but in order
+     * to improve the algorithm, we will read the 14 bytes we may be
+     * interested in */
+    p_header_data = p_pes->p_first;
+    i_done = 0;
+
+    for( ; ; )
+    {
+        i_todo = p_header_data->p_payload_end
+                     - p_header_data->p_payload_start;
+        if( i_todo > PES_HEADER_SIZE - i_done )
+            i_todo = PES_HEADER_SIZE - i_done;
+
+        memcpy( p_header + i_done, p_header_data->p_payload_start,
+                i_todo );
+        i_done += i_todo;
+
+        if( i_done < PES_HEADER_SIZE && p_header_data->p_next != NULL )
+        {
+            p_header_data = p_header_data->p_next;
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    if( i_done != PES_HEADER_SIZE )
+    {
+        intf_WarnMsg( 3, "PES packet too short to have a header" );
+        p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
+        p_pes = NULL;
+        return;
+    }
+
+    /* Get the PES size if defined */
+    p_es->i_pes_real_size = U16_AT(p_header + 4) + 6;
+
+    /* First read the 6 header bytes common to all PES packets:
+     * use them to test the PES validity */
+    if( (p_header[0] || p_header[1] || (p_header[2] != 1)) )
+    {
+        /* packet_start_code_prefix != 0x000001 */
+        intf_ErrMsg( "PES packet doesn't start with 0x000001 : data loss" );
+        p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
+        p_pes = NULL;
+    }
+    else
+    {
+        int i_pes_header_size, i_payload_size;
+
+        if ( p_es->i_pes_real_size &&
+             (p_es->i_pes_real_size != p_pes->i_pes_size) )
+        {
+            /* PES_packet_length is set and != total received payload */
+            /* Warn the decoder that the data may be corrupt. */
+            intf_WarnMsg( 3, "PES sizes do not match : packet corrupted" );
+            p_pes->b_messed_up = 1;
+        }
+
+        switch( p_es->i_stream_id )
+        {
+        case 0xBC:  /* Program stream map */
+        case 0xBE:  /* Padding */
+        case 0xBF:  /* Private stream 2 */
+        case 0xB0:  /* ECM */
+        case 0xB1:  /* EMM */
+        case 0xFF:  /* Program stream directory */
+        case 0xF2:  /* DSMCC stream */
+        case 0xF8:  /* ITU-T H.222.1 type E stream */
+            /* The payload begins immediately after the 6 bytes header, so
+             * we have finished with the parsing */
+            i_pes_header_size = 6;
+            break;
+
+        default:
+            /* The PES header contains at least 3 more bytes. */
+            p_pes->b_data_alignment = p_header[6] & 0x04;
+            p_pes->b_has_pts = p_header[7] & 0x80;
+            i_pes_header_size = p_header[8] + 9;
+
+            /* Now parse the optional header extensions (in the limit of
+             * the 14 bytes). */
+            if( p_pes->b_has_pts )
+            {
+                p_pes->i_pts =
+                  ( ((mtime_t)(p_header[9] & 0x0E) << 29) |
+                    (((mtime_t)U16_AT(p_header + 10) << 14) - (1 << 14)) |
+                    ((mtime_t)U16_AT(p_header + 12) >> 1) ) * 300;
+                p_pes->i_pts /= 27;
+
+                switch( p_es->p_pgrm->i_synchro_state )
+                {
+                case SYNCHRO_NOT_STARTED:
+                    p_pes->b_has_pts = 0;
+                    break;
+
+                case SYNCHRO_START:
+                    p_pes->i_pts += p_es->p_pgrm->delta_cr;
+                    p_es->p_pgrm->delta_absolute = mdate()
+                                     - p_pes->i_pts + DEFAULT_PTS_DELAY;
+                    p_pes->i_pts += p_es->p_pgrm->delta_absolute;
+                    p_es->p_pgrm->i_synchro_state = SYNCHRO_OK;
+                    break;
+
+                case SYNCHRO_REINIT: /* We skip a PES | Why ?? --Meuuh */
+                    p_pes->b_has_pts = 0;
+                    p_es->p_pgrm->i_synchro_state = SYNCHRO_START;
+                    break;
+
+                case SYNCHRO_OK:
+                    p_pes->i_pts += p_es->p_pgrm->delta_cr
+                                         + p_es->p_pgrm->delta_absolute;
+                    break;
+                }
+            }
+            break;
+        }
+
+        /* Now we've parsed the header, we just have to indicate in some
+         * specific data packets where the PES payload begins (renumber
+         * p_payload_start), so that the decoders can find the beginning
+         * of their data right out of the box. */
+        p_header_data = p_pes->p_first;
+        i_payload_size = p_header_data->p_payload_end
+                                 - p_header_data->p_payload_start;
+        while( i_pes_header_size > i_payload_size )
+        {
+            /* These packets are entirely filled by the PES header. */
+            i_pes_header_size -= i_payload_size;
+            p_header_data->p_payload_start = p_header_data->p_payload_end;
+            /* Go to the next data packet. */
+            if( (p_header_data = p_header_data->p_next) == NULL )
+            {
+                intf_ErrMsg( "PES header bigger than payload" );
+                p_input->p_plugin->pf_delete_pes( p_input->p_method_data,
+                                                  p_pes );
+                p_pes = NULL;
+                return;
+            }
+            i_payload_size = p_header_data->p_payload_end
+                                 - p_header_data->p_payload_start;
+        }
+        /* This last packet is partly header, partly payload. */
+        if( i_payload_size < i_pes_header_size )
+        {
+            intf_ErrMsg( "PES header bigger than payload" );
+            p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
+            p_pes = NULL;
+            return;
+        }
+        p_header_data->p_payload_start += i_pes_header_size;
+
+        /* Now we can eventually put the PES packet in the decoder's
+         * PES fifo */
+        input_DecodePES( p_input, p_es );
+    }
+#undef p_pes
+}
+
+/*****************************************************************************
+ * input_GatherPES:
+ *****************************************************************************
+ * Gather a PES packet.
+ *****************************************************************************/
+void input_GatherPES( input_thread_t * p_input, data_packet_t *p_data,
+                      es_descriptor_t * p_es,
+                      boolean_t b_unit_start, boolean_t b_packet_lost )
+{
+#define p_pes (p_es->p_pes)
+
+    //intf_DbgMsg("PES-demultiplexing %p (%p)\n", p_ts_packet, p_pes);
+
+    /* If we lost data, insert an NULL data packet (philosophy : 0 is quite
+     * often an escape sequence in decoders, so that should make them wait
+     * for the next start code). */
+    if( b_packet_lost && p_pes != NULL )
+    {
+        data_packet_t *             p_pad_data;
+        if( (p_pad_data = p_input->p_plugin->pf_new_packet( p_input,
+                                            PADDING_PACKET_SIZE )) == NULL )
+        {
+            intf_ErrMsg("Out of memory\n");
+            p_input->b_error = 1;
+            return;
+        }
+        memset( p_data->p_buffer, 0, PADDING_PACKET_SIZE );
+        p_pad_data->b_discard_payload = 1;
+        p_pes->b_messed_up = 1;
+        input_GatherPES( p_input, p_pad_data, p_es, 0, 0 );
+    }
+
+    if( b_unit_start && p_pes != NULL )
+    {
+        /* If the TS packet contains the begining of a new PES packet, and
+         * if we were reassembling a PES packet, then the PES should be
+         * complete now, so parse its header and give it to the decoders. */
+        input_ParsePES( p_input, p_es );
+    }
+
+    if( !b_unit_start && p_pes == NULL )
+    {
+        /* Random access... */
+        p_input->p_plugin->pf_delete_packet( p_input->p_method_data, p_data );
+    }
+    else
+    {
+        if( b_unit_start )
+        {
+            /* If we are at the beginning of a new PES packet, we must fetch
+             * a new PES buffer to begin with the reassembly of this PES
+             * packet. This is also here that we can synchronize with the
+             * stream if we lost packets or if the decoder has just
+             * started. */
+            if( (p_pes = (pes_packet_t *)malloc( sizeof(pes_packet_t) )) == NULL )
+            {
+                intf_ErrMsg("Out of memory");
+                p_input->b_error = 1;
+                return;
+            }
+            //intf_DbgMsg("New PES packet %p (first data: %p)\n", p_pes, p_data);
+
+            /* Init the PES fields so that the first data packet could be
+             * correctly added to the PES packet (see below). */
+            p_pes->p_first = p_data;
+            p_pes->b_messed_up = p_pes->b_discontinuity = 0;
+            p_pes->i_pes_size = 0;
+
+            /* 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
+                    >= PES_HEADER_SIZE )
+            {
+                p_es->i_pes_real_size =
+                                U16_AT(p_data->p_payload_start + 4) + 6;
+            }
+            else
+            {
+                p_es->i_pes_real_size = 0;
+            }
+        }
+        else
+        {
+            /* Update the relations between the data packets */
+            p_es->p_last->p_next = p_data;
+        }
+
+        p_data->p_next = NULL;
+        p_es->p_last = p_data;
+
+        /* Size of the payload carried in the data packet */
+        p_pes->i_pes_size += (p_data->p_payload_end
+                                 - p_data->p_payload_start);
+    
+        /* We can check if the packet is finished */
+        if( p_pes->i_pes_size == p_es->i_pes_real_size )
+        {
+            /* The packet is finished, parse it */
+            input_ParsePES( p_input, p_es );
+        }
+    }
+#undef p_pes
+}
+
+
+/*
+ * Pace control
+ */
+
+/*
+ *   DISCUSSION : SYNCHRONIZATION METHOD
+ *
+ *   In some cases we can impose the pace of reading (when reading from a
+ *   file or a pipe), and for the synchronization we simply sleep() until
+ *   it is time to deliver the packet to the decoders. When reading from
+ *   the network, we must be read at the same pace as the server writes,
+ *   otherwise the kernel's buffer will trash packets. The risk is now to
+ *   overflow the input buffers in case the server goes too fast, that is
+ *   why we do these calculations :
+ *
+ *   We compute an average for the pcr because we want to eliminate the
+ *   network jitter and keep the low frequency variations. The average is
+ *   in fact a low pass filter and the jitter is a high frequency signal
+ *   that is why it is eliminated by the filter/average.
+ *
+ *   The low frequency variations enable us to synchronize the client clock
+ *   with the server clock because they represent the time variation between
+ *   the 2 clocks. Those variations (ie the filtered pcr) are used to compute
+ *   the presentation dates for the audio and video frames. With those dates
+ *   we can decode (or trash) the MPEG2 stream at "exactly" the same rate
+ *   as it is sent by the server and so we keep the synchronization between
+ *   the server and the client.
+ *
+ *   It is a very important matter if you want to avoid underflow or overflow
+ *   in all the FIFOs, but it may be not enough.
+ */
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+
+/* Maximum number of samples used to compute the dynamic average value,
+ * it is also the maximum of c_average_count in pgrm_ts_data_t.
+ * We use the following formula :
+ * new_average = (old_average * c_average + new_sample_value) / (c_average +1) */
+#define CR_MAX_AVERAGE_COUNTER 40
+
+/* Maximum gap allowed between two CRs. */
+#define CR_MAX_GAP 1000000
+
+/*****************************************************************************
+ * CRReInit : Reinitialize the clock reference
+ *****************************************************************************/
+static void CRReInit( pgrm_descriptor_t * p_pgrm )
+{
+    p_pgrm->delta_cr        = 0;
+    p_pgrm->last_cr         = 0;
+    p_pgrm->c_average_count = 0;
+}
+
+/* FIXME: find a better name */
+/*****************************************************************************
+ * CRDecode : Decode a clock reference
+ *****************************************************************************/
+static void CRDecode( input_thread_t * p_input, es_descriptor_t * p_es,
+                      mtime_t cr_time )
+{
+    pgrm_descriptor_t *     p_pgrm;
+    if( p_es != NULL )
+    {
+        p_pgrm = p_es->p_pgrm;
+    }
+    else
+    {
+        p_pgrm = p_input->stream.pp_programs[0];
+    }
+
+    if( p_input->stream.b_pace_control )
+    {
+        /* Wait a while before delivering the packets to the decoder. */
+        mwait( cr_time + p_pgrm->delta_absolute );
+    }
+    else
+    {
+        mtime_t                 sys_time, delta_cr;
+
+        sys_time = mdate();
+        delta_cr = sys_time - cr_time;
+
+        if( (p_es != NULL && p_es->b_discontinuity) ||
+            ( p_pgrm->last_cr != 0 &&
+                  (    (p_pgrm->last_cr - cr_time) > CR_MAX_GAP
+                    || (p_pgrm->last_cr - cr_time) < - CR_MAX_GAP ) ) )
+        {
+            intf_WarnMsg( 3, "CR re-initialiazed" );
+            CRReInit( p_pgrm );
+            p_pgrm->i_synchro_state = SYNCHRO_REINIT;
+            if( p_es != NULL )
+            {
+                p_es->b_discontinuity = 0;
+            }
+        }
+        p_pgrm->last_cr = cr_time;
+
+        if( p_pgrm->c_average_count == CR_MAX_AVERAGE_COUNTER )
+        {
+            p_pgrm->delta_cr = ( delta_cr + (p_pgrm->delta_cr
+                                              * (CR_MAX_AVERAGE_COUNTER - 1)) )
+                                 / CR_MAX_AVERAGE_COUNTER;
+        }
+        else
+        {
+            p_pgrm->delta_cr = ( delta_cr + (p_pgrm->delta_cr
+                                              * p_pgrm->c_average_count) )
+                                 / ( p_pgrm->c_average_count + 1 );
+            p_pgrm->c_average_count++;
+        }
+
+        if( p_pgrm->i_synchro_state == SYNCHRO_NOT_STARTED )
+        {
+            p_pgrm->i_synchro_state = SYNCHRO_START;
+        }
+    }
+}
+
+
+/*
+ * PS Demultiplexing
+ */
+
+/*****************************************************************************
+ * DecodePSM: Decode the Program Stream Map information
+ *****************************************************************************/
+static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
+{
+    stream_ps_data_t *  p_demux =
+                 (stream_ps_data_t *)p_input->stream.p_demux_data;
+
+    if( !p_demux->b_is_PSM_complete )
+    {
+        byte_t *    p_byte;
+        byte_t *    p_end;
+        int         i_es = 0;
+
+        intf_DbgMsg( "Building PSM" );
+        if( p_data->p_payload_start + 10 > p_data->p_payload_end )
+        {
+            intf_ErrMsg( "PSM too short : packet corrupt" );
+            return;
+        }
+        /* Go to elementary_stream_map_length, jumping over
+         * program_stream_info. */
+        p_byte = p_data->p_payload_start + 10
+                  + U16_AT(&p_data->p_payload_start[8]);
+        if( p_byte > p_data->p_payload_end )
+        {
+            intf_ErrMsg( "PSM too short : packet corrupt" );
+            return;
+        }
+        /* This is the full size of the elementary_stream_map.
+         * 2 == elementary_stream_map_length
+         * 4 == CRC_32 */
+        p_end = p_byte + 2 + U16_AT(p_byte) - 4;
+        p_byte += 2;
+        if( p_end > p_data->p_payload_end )
+        {
+            intf_ErrMsg( "PSM too short : packet corrupt" );
+            return;
+        }
+
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+
+        /* 4 == minimum useful size of a section */
+        while( p_byte + 4 <= p_end )
+        {
+            p_input->p_es[i_es].i_id
+                = p_input->p_es[i_es].i_stream_id
+                = p_byte[1];
+            p_input->p_es[i_es].i_type = p_byte[0];
+            p_input->p_es[i_es].p_pgrm = p_input->stream.pp_programs[0];
+            p_input->p_es[i_es].b_discontinuity = 0;
+            p_input->p_es[i_es].p_pes = NULL;
+            p_byte += 4 + U16_AT(&p_byte[2]);
+
+#ifdef AUTO_SPAWN
+            switch( p_input->p_es[i_es].i_type )
+            {
+                case MPEG1_AUDIO_ES:
+                case MPEG2_AUDIO_ES:
+                    /* Spawn audio thread. */
+                    intf_DbgMsg( "Starting an MPEG-audio decoder" );
+                    break;
+
+                case MPEG1_VIDEO_ES:
+                case MPEG2_VIDEO_ES:
+                    /* Spawn video thread. */
+                    intf_DbgMsg( "Starting an MPEG-video decoder" );
+                    break;
+            }
+#endif
+
+            i_es++;
+        }
+
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+        p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F;
+        p_demux->b_is_PSM_complete = 1;
+    }
+    else if( p_demux->i_PSM_version != (p_data->p_buffer[6] & 0x1F) )
+    {
+        /* FIXME */
+        intf_ErrMsg( "PSM changed, this is not supported yet !" );
+        p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F;
+    }
+}
+
+/*****************************************************************************
+ * input_DemuxPS: first step of demultiplexing: the PS header
+ *****************************************************************************/
+void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
+{
+    u32                 i_code;
+    boolean_t           b_trash = 0;
+    es_descriptor_t *   p_es = NULL;
+
+    i_code = U32_AT( p_data->p_buffer );
+    if( i_code >= 0x1B9 && i_code <= 0x1BC )
+    {
+        switch( i_code )
+        {
+        case 0x1BA: /* PACK_START_CODE */
+            if( p_input->stream.pp_programs[0]->i_synchro_state == SYNCHRO_OK )
+            {
+                /* Convert the SCR in microseconds. */
+                mtime_t         scr_time;
+                scr_time = (( ((mtime_t)(p_data->p_buffer[4] & 0x38) << 27) |
+                              ((mtime_t)(p_data->p_buffer[4] & 0x3) << 26) |
+                              ((mtime_t)(p_data->p_buffer[5]) << 20) |
+                              ((mtime_t)(p_data->p_buffer[6] & 0xF8) << 12) |
+                              ((mtime_t)(p_data->p_buffer[6] & 0x3) << 13) |
+                              ((mtime_t)(p_data->p_buffer[7]) << 5) |
+                              ((mtime_t)(p_data->p_buffer[8] & 0xF8) >> 3)
+                           ) * 300) / 27;
+
+                /* Call the pace control. */
+                CRDecode( p_input, NULL, scr_time );
+            }
+            b_trash = 1;
+            break;
+
+        case 0x1BB: /* SYSTEM_START_CODE */
+            b_trash = 1;                              /* Nothing interesting */
+            break;
+
+        case 0x1BC: /* PROGRAM_STREAM_MAP_CODE */
+            intf_ErrMsg("meuuuuh\n");
+            DecodePSM( p_input, p_data );
+            b_trash = 1;
+            break;
+    
+        case 0x1B9: /* PROGRAM_END_CODE */
+            b_trash = 1;
+            break;
+   
+        default:
+            /* This should not happen */
+            b_trash = 1;
+            intf_WarnMsg( 1, "Unwanted packet received with start code %x",
+                          i_code );
+        }
+    }
+    else
+    {
+        u16                 i_id;
+        int                 i_dummy;
+
+        /* This is a PES packet. Find out if we want it or not. */
+        i_id = p_data->p_buffer[3];                     /* ID of the stream. */
+
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        for( i_dummy = 0; i_dummy < INPUT_MAX_ES; i_dummy++ )
+        {
+            if( p_input->p_es[i_dummy].i_id == i_id )
+            {
+                p_es = &p_input->p_es[i_dummy];
+                break;
+            }
+        }
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+        if( p_es == NULL )
+        {
+#if 1
+            /* FIXME ! */
+            if( (i_id & 0xC0L) == 0xC0L )
+            {
+                /* MPEG video and audio */
+                for( i_dummy = 0; i_dummy < INPUT_MAX_ES; i_dummy++ )
+                {
+                    if( p_input->p_es[i_dummy].i_id == EMPTY_ID )
+                    {
+                        p_es = &p_input->p_es[i_dummy];
+                        break;
+                    }
+                }
+
+                if( p_es != NULL && (i_id & 0xF0L) == 0xE0L )
+                {
+                    /* MPEG video */
+                    vdec_config_t * p_config;
+                    p_es->i_id = p_es->i_stream_id = i_id;
+                    p_es->i_type = MPEG2_VIDEO_ES;
+                    p_es->p_pgrm = p_input->stream.pp_programs[0];
+                    p_es->b_discontinuity = 0;
+                    p_es->p_pes = NULL;
+
+#ifdef AUTO_SPAWN
+                    p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) );
+                    p_config->p_vout = p_input->p_default_vout;
+                    /* FIXME ! */
+                    p_config->decoder_config.i_stream_id = i_id;
+                    p_config->decoder_config.i_type = MPEG2_VIDEO_ES;
+                    p_config->decoder_config.p_stream_ctrl =
+                        &p_input->stream.control;
+                    p_config->decoder_config.p_decoder_fifo =
+                        (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) );
+                    vlc_mutex_init(&p_config->decoder_config.p_decoder_fifo->data_lock);
+                    vlc_cond_init(&p_config->decoder_config.p_decoder_fifo->data_wait);
+                    p_config->decoder_config.p_decoder_fifo->i_start =
+                        p_config->decoder_config.p_decoder_fifo->i_end = 0;
+                    p_config->decoder_config.p_decoder_fifo->b_die = 0;
+                    p_config->decoder_config.p_decoder_fifo->p_packets_mgt =
+                        p_input->p_method_data;
+                    p_config->decoder_config.p_decoder_fifo->pf_delete_pes =
+                        p_input->p_plugin->pf_delete_pes;
+                    p_es->p_decoder_fifo = p_config->decoder_config.p_decoder_fifo;
+                    p_config->decoder_config.pf_init_bit_stream =
+                        InitBitstream;
+                    for( i_dummy = 0; i_dummy < INPUT_MAX_SELECTED_ES; i_dummy++ )
+                    {
+                        if( p_input->pp_selected_es[i_dummy] == NULL )
+                        {
+                            p_input->pp_selected_es[i_dummy] = p_es;
+                            break;
+                        }
+                    }
+
+                    p_es->thread_id = vpar_CreateThread( p_config );
+#endif
+                }
+                else if( p_es != NULL && (i_id & 0xE0) == 0xC0 )
+                {
+                    /* MPEG audio */
+                    adec_config_t * p_config;
+                    p_es->i_id = p_es->i_stream_id = i_id;
+                    p_es->i_type = MPEG2_AUDIO_ES;
+                    p_es->p_pgrm = p_input->stream.pp_programs[0];
+                    p_es->b_discontinuity = 0;
+                    p_es->p_pes = NULL;
+
+#ifdef AUTO_SPAWN
+                    p_config = (adec_config_t *)malloc( sizeof(adec_config_t) );
+                    p_config->p_aout = p_input->p_default_aout;
+                    /* FIXME ! */
+                    p_config->decoder_config.i_stream_id = i_id;
+                    p_config->decoder_config.i_type = MPEG2_AUDIO_ES;
+                    p_config->decoder_config.p_stream_ctrl =
+                        &p_input->stream.control;
+                    p_config->decoder_config.p_decoder_fifo =
+                        (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) );
+                    vlc_mutex_init(&p_config->decoder_config.p_decoder_fifo->data_lock);
+                    vlc_cond_init(&p_config->decoder_config.p_decoder_fifo->data_wait);
+                    p_config->decoder_config.p_decoder_fifo->i_start =
+                        p_config->decoder_config.p_decoder_fifo->i_end = 0;
+                    p_config->decoder_config.p_decoder_fifo->b_die = 0;
+                    p_config->decoder_config.p_decoder_fifo->p_packets_mgt =
+                        p_input->p_method_data;
+                    p_config->decoder_config.p_decoder_fifo->pf_delete_pes =
+                        p_input->p_plugin->pf_delete_pes;
+                    p_es->p_decoder_fifo = p_config->decoder_config.p_decoder_fifo;
+                    p_config->decoder_config.pf_init_bit_stream =
+                        InitBitstream;
+                    for( i_dummy = 0; i_dummy < INPUT_MAX_SELECTED_ES; i_dummy++ )
+                    {
+                        if( p_input->pp_selected_es[i_dummy] == NULL )
+                        {
+                            p_input->pp_selected_es[i_dummy] = p_es;
+                            break;
+                        }
+                    }
+
+                    p_es->thread_id = adec_CreateThread( p_config );
+#endif
+                }
+                else
+                {
+                    b_trash = 1;
+                }
+            }
+            else
+                b_trash = 1;
+#else
+            b_trash = 1;
+#endif
+        }
+        else
+        {
+#ifdef STATS
+            p_es->c_packets++;
+#endif
+            input_GatherPES( p_input, p_data, p_es, 1, 0 );
+        }
+    }
+
+    /* Trash the packet if it has no payload or if it isn't selected */
+    if( b_trash )
+    {
+        p_input->p_plugin->pf_delete_packet( p_input, p_data );
+#ifdef STATS
+        p_input->c_packets_trashed++;
+#endif
+    }
+}
+
+
+/*
+ * TS Demultiplexing
+ */
+
+/*****************************************************************************
+ * input_DemuxTS: first step of demultiplexing: the TS header
+ *****************************************************************************/
+void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
+{
+    int                 i_pid, i_dummy;
+    boolean_t           b_adaptation;         /* Adaptation field is present */
+    boolean_t           b_payload;                 /* Packet carries payload */
+    boolean_t           b_unit_start;  /* A PSI or a PES start in the packet */
+    boolean_t           b_trash = 0;             /* Is the packet unuseful ? */
+    boolean_t           b_lost = 0;             /* Was there a packet loss ? */
+    es_descriptor_t *   p_es = NULL;
+    es_ts_data_t *      p_es_demux = NULL;
+    pgrm_ts_data_t *    p_pgrm_demux = NULL;
+
+#define p (p_data->p_buffer)
+
+    //intf_DbgMsg("input debug: TS-demultiplexing packet %p, pid %d\n",
+    //            p_ts_packet, U16_AT(&p[1]) & 0x1fff);
+
+    /* Extract flags values from TS common header. */
+    i_pid = U16_AT(&p[1]) & 0x1fff;
+    b_unit_start = (p[1] & 0x40);
+    b_adaptation = (p[3] & 0x20);
+    b_payload = (p[3] & 0x10);
+
+    /* Find out the elementary stream. */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    for( i_dummy = 0; i_dummy < INPUT_MAX_ES; i_dummy++ )
+    {
+        if( p_input->p_es[i_dummy].i_id != EMPTY_ID )
+        {
+            if( p_input->p_es[i_dummy].i_id == i_pid )
+            {
+                p_es = &p_input->p_es[i_dummy];
+                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;
+                break;
+            }
+        }
+    }
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+#ifdef STATS
+    p_es->c_packets++;
+#endif
+
+    if( p_es->p_decoder_fifo == NULL )
+    {
+        /* Not selected. Just read the adaptation field for a PCR. */
+        b_trash = 1;
+    }
+
+    if( (p_es->p_decoder_fifo != NULL) || (p_pgrm_demux->i_pcr_pid == i_pid) )
+    {
+        /* Extract adaptation field information if any */
+        if( !b_adaptation )
+        {
+            /* We don't have any adaptation_field, so payload starts
+             * immediately after the 4 byte TS header */
+            p_data->p_payload_start += 4;
+        }
+        else
+        {
+            /* p[4] is adaptation_field_length minus one */
+            p_data->p_payload_start += 5 + p[4];
+    
+            /* The adaptation field can be limited to the
+             * adaptation_field_length byte, so that there is nothing to do:
+             * skip this possibility */
+            if( p[4] )
+            {
+                /* If the packet has both adaptation_field and payload,
+                 * adaptation_field cannot be more than 182 bytes long; if
+                 * there is only an adaptation_field, it must fill the next
+                 * 183 bytes. */
+                if( b_payload ? (p[4] > 182) : (p[4] != 183) )
+                {
+                    intf_WarnMsg( 2,
+                        "invalid TS adaptation field (%p)",
+                        p_data );
+                    p_data->b_discard_payload = 1;
+#ifdef STATS
+                    p_es->c_invalid_packets++;
+#endif
+                }
+    
+                /* Now we are sure that the byte containing flags is present:
+                 * read it */
+                else
+                {
+                    /* discontinuity_indicator */
+                    if( p[5] & 0x80 )
+                    {
+                        intf_WarnMsg( 2,
+                            "discontinuity_indicator"                       \
+                            " encountered by TS demux (position read: %d,"  \
+                            " saved: %d)",
+                            p[5] & 0x80, p_es_demux->i_continuity_counter );
+    
+                        /* If the PID carries the PCR, there will be a system
+                         * time-based discontinuity. We let the PCR decoder
+                         * handle that. */
+                        p_es->b_discontinuity = 1;
+    
+                        /* There also may be a continuity_counter
+                         * discontinuity: resynchronise our counter with
+                         * the one of the stream. */
+                        p_es_demux->i_continuity_counter = (p[3] & 0x0f) - 1;
+                    }
+    
+                    /* 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
+                         * if the adaptation field is long enough to carry
+                         * it. */
+                        if( p[4] >= 7 )
+                        {
+                            /* Convert the PCR in microseconds.
+                             * WARNING: do not remove the casts in the
+                             * following calculation ! */
+                            mtime_t     pcr_time;
+                            pcr_time =
+                                    ( (( (mtime_t)U32_AT((u32*)&p[6]) << 1 )
+                                      | ( p[10] >> 7 )) * 300 ) / 27;
+                            /* Call the pace control. */
+                            CRDecode( p_input, p_es, pcr_time );
+                        }
+                    } /* PCR ? */
+                } /* 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++;
+        }
+        else
+        {
+            if( !b_payload && i_dummy == 0 )
+            {
+                /* This is a packet without payload, this is allowed by the draft.
+                 * As there is nothing interesting in this packet (except PCR that
+                 * have already been handled), we can trash the packet. */
+                intf_WarnMsg( 1,
+                              "Packet without payload received by TS demux" );
+                b_trash = 1;
+            }
+            else if( i_dummy <= 0 )
+            {
+                /* FIXME: this can never happen, can it ? --Meuuh */
+                /* Duplicate packet: mark it as being to be trashed. */
+                intf_WarnMsg( 1, "Duplicate packet received by TS demux" );
+                b_trash = 1;
+            }
+            else if( p_es_demux->i_continuity_counter == 0xFF )
+            {
+                /* This means that the packet is the first one we receive for this
+                 * ES since the continuity counter ranges between 0 and 0x0F
+                 * excepts when it has been initialized by the input: Init the
+                 * counter to the correct value. */
+                intf_DbgMsg( "First packet for PID %d received by TS demux",
+                             p_es->i_id );
+                p_es_demux->i_continuity_counter = (p[3] & 0x0f);
+            }
+            else
+            {
+                /* This can indicate that we missed a packet or that the
+                 * continuity_counter wrapped and we received a dup packet: as we
+                 * don't know, do as if we missed a packet to be sure to recover
+                 * from this situation */
+                intf_WarnMsg( 2,
+                           "Packet lost by TS demux: current %d, packet %d\n",
+                           p_es_demux->i_continuity_counter & 0x0f,
+                           p[3] & 0x0f );
+                b_lost = 1;
+                p_es_demux->i_continuity_counter = p[3] & 0x0f;
+            } /* not continuous */
+        } /* continuity */
+    } /* if selected or PCR */
+
+    /* Trash the packet if it has no payload or if it isn't selected */
+    if( b_trash )
+    {
+        p_input->p_plugin->pf_delete_packet( p_input, p_data );
+#ifdef STATS
+        p_input->c_packets_trashed++;
+#endif
+    }
+    else
+    {
+        if( p_es_demux->b_psi )
+        {
+            /* The payload contains PSI tables */
+#if 0
+            input_DemuxPSI( p_input, p_data, p_es,
+                            b_unit_start, b_lost );
+#endif
+        }
+        else
+        {
+            /* The payload carries a PES stream */
+            if( b_unit_start )
+            input_GatherPES( p_input, p_data, p_es, b_unit_start, b_lost );
+        }
+    }
+
+#undef p
+}
diff --git a/src/input/mpeg_system.h b/src/input/mpeg_system.h
new file mode 100644 (file)
index 0000000..f1f1855
--- /dev/null
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define TS_PACKET_SIZE      188                       /* Size of a TS packet */
+#define PSI_SECTION_SIZE    4096            /* Maximum size of a PSI section */
+#define PADDING_PACKET_SIZE 100 /* Size of the NULL packet inserted in case
+                                 * of data loss (this should be < 188).      */
+
+
+/*****************************************************************************
+ * psi_section_t
+ *****************************************************************************
+ * Describes a PSI section. Beware, it doesn't contain pointers to the TS
+ * packets that contain it as for a PES, but the data themselves
+ *****************************************************************************/
+typedef struct psi_section_s
+{
+    byte_t                  buffer[PSI_SECTION_SIZE];
+
+    /* Is there a section being decoded ? */
+    boolean_t               b_running_section;
+
+    u16                     i_length;
+    u16                     i_current_position;
+} psi_section_t;
+
+/*****************************************************************************
+ * es_ts_data_t: extension of es_descriptor_t
+ *****************************************************************************/
+typedef struct es_ts_data_s
+{
+    boolean_t               b_psi;   /* Does the stream have to be handled by
+                                      *                    the PSI decoder ? */
+    psi_section_t *         p_psi_section;                    /* PSI packets */
+
+    /* Markers */
+    int                     i_continuity_counter;
+} es_ts_data_t;
+
+/*****************************************************************************
+ * pgrm_ts_data_t: extension of pgrm_descriptor_t
+ *****************************************************************************/
+typedef struct pgrm_ts_data_s
+{
+    u16                     i_pcr_pid;             /* PCR ES, for TS streams */
+} pgrm_ts_data_t;
+
+/*****************************************************************************
+ * stream_ts_data_t: extension of stream_descriptor_t
+ *****************************************************************************/
+typedef struct stream_ts_data_s
+{
+    /* Program Association Table status */
+    u8                      i_PAT_version;                 /* version number */
+    boolean_t               b_is_PAT_complete;      /* Is the PAT complete ? */
+    u8                      i_known_PAT_sections;
+                                     /* Number of section we received so far */
+    byte_t                  a_known_PAT_sections[32];
+                                                /* Already received sections */
+
+    /* Program Map Table status */
+    boolean_t               b_is_PMT_complete;      /* Is the PMT complete ? */
+    u8                      i_known_PMT_sections;
+                                     /* Number of section we received so far */
+    byte_t                  a_known_PMT_sections[32];
+                                                /* Already received sections */
+
+    /* Service Description Table status */
+    u8                      i_SDT_version;                 /* version number */
+    boolean_t               b_is_SDT_complete;      /* Is the SDT complete ? */
+    u8                      i_known_SDT_sections;
+                                     /* Number of section we received so far */
+    byte_t                  a_known_SDT_sections[32];
+                                                /* Already received sections */
+} stream_ts_data_t;
+
+/*****************************************************************************
+ * stream_ps_data_t: extension of stream_descriptor_t
+ *****************************************************************************/
+typedef struct stream_ps_data_s
+{
+    u8                      i_PSM_version;
+    boolean_t               b_is_PSM_complete;
+} stream_ps_data_t;
+
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void input_DecodePES( struct input_thread_s *, struct es_descriptor_s * );
+void input_ParsePES( struct input_thread_s *, struct es_descriptor_s * );
+void input_GatherPES( struct input_thread_s *, struct data_packet_s *,
+                      struct es_descriptor_s *, boolean_t, boolean_t );
+void input_DemuxPS( struct input_thread_s *, struct data_packet_s * );
+void input_DemuxTS( struct input_thread_s *, struct data_packet_s * );
index f6c4a19e76424188e641da3286310c4ae7f8a420..d901bc6a6e616729b0efe5c3a9629986ca001338 100644 (file)
@@ -40,7 +40,8 @@
 #include "mtime.h"
 #include "plugins.h"
 #include "playlist.h"
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
 
 #include "audio_output.h"
 
@@ -176,18 +177,43 @@ intf_thread_t* intf_Create( void )
 void intf_Run( intf_thread_t *p_intf )
 {
     char * psz_server = main_GetPszVariable( INPUT_SERVER_VAR, NULL );
+    input_config_t *    p_input_config;
 
     /* If a server was specified */
     if( psz_server )
     {
-        p_intf->p_input = input_CreateThread( INPUT_METHOD_TS_UCAST,
-                              psz_server, 0, 0,
-                              p_intf->p_vout, p_main->p_aout, NULL );
+        if( (p_input_config =
+              (input_config_t *)malloc( sizeof(input_config_t) )) == NULL )
+        {
+            intf_ErrMsg("Out of memory");
+        }
+        else
+        {
+            p_input_config->i_method = INPUT_METHOD_UCAST;
+            p_input_config->p_source = psz_server;
+            p_input_config->p_default_aout = p_main->p_aout;
+            p_input_config->p_default_vout = p_intf->p_vout;
+
+            p_intf->p_input = input_CreateThread( p_input_config, NULL );
+        }
     }
     /* Or if a file was specified */
-    else if( p_main->p_playlist->p_list )
+    else if( p_main->p_playlist->p_list != NULL )
     {
-        p_intf->p_input = input_CreateThread( INPUT_METHOD_TS_FILE, NULL, 0, 0, p_main->p_intf->p_vout, p_main->p_aout, NULL );
+        if( (p_input_config =
+              (input_config_t *)malloc( sizeof(input_config_t) )) == NULL )
+        {
+            intf_ErrMsg("Out of memory");
+        }
+        else
+        {
+            p_input_config->i_method = INPUT_METHOD_FILE;
+            p_input_config->p_source = p_main->p_playlist->p_list[0]; /* FIXME ??? */
+            p_input_config->p_default_aout = p_main->p_aout;
+            p_input_config->p_default_vout = p_intf->p_vout;
+
+            p_intf->p_input = input_CreateThread( p_input_config, NULL );
+        }
     }
     /* Execute the initialization script - if a positive number is returned,
      * the script could be executed but failed */
@@ -262,6 +288,8 @@ void intf_Destroy( intf_thread_t *p_intf )
  *****************************************************************************/
 int intf_SelectChannel( intf_thread_t * p_intf, int i_channel )
 {
+    /* FIXME */
+#if 0
     intf_channel_t *    p_channel;                                /* channel */
 
     /* Look for channel in array */
@@ -294,6 +322,7 @@ int intf_SelectChannel( intf_thread_t * p_intf, int i_channel )
 
     /* Channel does not exist */
     intf_Msg("Channel %d does not exist\n", i_channel );
+#endif
     return( 1 );
 }
 
index 593787064797ed75abe98d6b3bface4b7742685a..6996dc61ade413a74c4b866cba311914ba9f4bc5 100644 (file)
@@ -59,7 +59,8 @@
 #include "plugins.h"
 #include "intf_msg.h"
 
-#include "input.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
 #include "audio_output.h"
 #include "intf_cmd.h"
 #include "interface.h"
@@ -463,6 +464,8 @@ static int SpawnInput( int i_argc, intf_arg_t *p_argv )
     int                 i_port = 0;                        /* port parameter */
     int                 i_vlan = 0;                        /* vlan parameter */
 
+    /* FIXME */
+#if 0
     /* Parse parameters - see command list above */
     for ( i_arg = 1; i_arg < i_argc; i_arg++ )
     {
@@ -495,6 +498,7 @@ static int SpawnInput( int i_argc, intf_arg_t *p_argv )
                                                   p_main->p_intf->p_vout, p_main->p_aout,
                                                   NULL );
     return( INTF_NO_ERROR );
+#endif
 }
 
 /*****************************************************************************
index e368383e364505453150a31c17ed76ce31421542..5f59c94cc50fe4526dcc0bdda7849c762ddbe535 100644 (file)
@@ -42,8 +42,8 @@
 #include "tests.h"                                              /* TestMMX() */
 #include "plugins.h"
 #include "playlist.h"
-#include "input_vlan.h"
-#include "input_ps.h"
+#include "stream_control.h"
+#include "input_ext-intf.h"
 
 #include "intf_msg.h"
 #include "interface.h"
@@ -241,6 +241,8 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
     /*
      * Initialize shared resources and libraries
      */
+    /* FIXME: no VLANs */
+#if 0
     if( p_main->b_vlans && input_VlanCreate() )
     {
         /* On error during vlans initialization, switch off vlans */
@@ -248,6 +250,7 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
                   "vlans management is deactivated\n" );
         p_main->b_vlans = 0;
     }
+#endif
 
     /*
      * Open audio device and start aout thread
@@ -290,10 +293,13 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
     /*
      * Free shared resources and libraries
      */
+    /* FIXME */
+#if 0
     if( p_main->b_vlans )
     {
         input_VlanDestroy();
     }
+#endif
 
     /*
      * Free plugin bank
@@ -519,6 +525,8 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
             main_PutPszVariable( YUV_METHOD_VAR, optarg );
             break;
 
+            /* FIXME */
+#if 0
         /* DVD options */
         case 'a':
             if ( ! strcmp(optarg, "mpeg") )
@@ -530,6 +538,7 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
             else
                 main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_AC3 );
             break;
+#endif
         case 'c':
             main_PutIntVariable( INPUT_DVD_CHANNEL_VAR, atoi(optarg) );
             break;
index a95515319205962af20cec4f8efdf75aff4a4782..d12f4e840267bf595c2aa431f295312be528ce87 100644 (file)
@@ -41,9 +41,8 @@
 
 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
 
-#include "input.h"                                           /* pes_packet_t */
-#include "input_netlist.h"                         /* input_NetlistFreePES() */
-#include "decoder_fifo.h"         /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
+#include "stream_control.h"
+#include "input_ext-dec.h"
 
 #include "audio_output.h"
 
@@ -63,7 +62,7 @@ static void     EndThread               (lpcmdec_thread_t * p_adec);
 /*****************************************************************************
  * lpcmdec_CreateThread: creates an lpcm decoder thread
  *****************************************************************************/
-lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
+vlc_thread_t lpcmdec_CreateThread (adec_config_t * p_config)
 {
     lpcmdec_thread_t *   p_lpcmdec;
     intf_DbgMsg ( "LPCM Debug: creating lpcm decoder thread\n" );
@@ -71,7 +70,7 @@ lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
     /* Allocate the memory needed to store the thread's structure */
     if ((p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t))) == NULL) {
         intf_ErrMsg ( "LPCM Error: not enough memory for lpcmdec_CreateThread() to create the new thread\n" );
-        return NULL;
+        return 0;
     }
 
     /*
@@ -79,58 +78,28 @@ lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
      */
     p_lpcmdec->b_die = 0;
     p_lpcmdec->b_error = 0;
+    p_lpcmdec->p_config = p_config;
+    p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
 
-    /*
-     * Initialize the input properties
-     */
-    /* Initialize the decoder fifo's data lock and conditional variable and set
-     * its buffer as empty */
-    vlc_mutex_init (&p_lpcmdec->fifo.data_lock);
-    vlc_cond_init (&p_lpcmdec->fifo.data_wait);
-    p_lpcmdec->fifo.i_start = 0;
-    p_lpcmdec->fifo.i_end = 0;
 
     /* Initialize the lpcm decoder structures */
     lpcm_init (&p_lpcmdec->lpcm_decoder);
 
-    /* Initialize the bit stream structure */
-    p_lpcmdec->p_input = p_input;
-
     /*
      * Initialize the output properties
      */
-    p_lpcmdec->p_aout = p_input->p_aout;
+    p_lpcmdec->p_aout = p_config->p_aout;
     p_lpcmdec->p_aout_fifo = NULL;
 
     /* Spawn the lpcm decoder thread */
     if (vlc_thread_create(&p_lpcmdec->thread_id, "lpcm decoder", (vlc_thread_func_t)RunThread, (void *)p_lpcmdec)) {
         intf_ErrMsg  ( "LPCM Error: can't spawn lpcm decoder thread\n" );
         free (p_lpcmdec);
-        return NULL;
+        return 0;
     }
 
     intf_DbgMsg ( "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec );
-    return p_lpcmdec;
-}
-
-/*****************************************************************************
- * lpcmdec_DestroyThread: destroys an lpcm decoder thread
- *****************************************************************************/
-void lpcmdec_DestroyThread (lpcmdec_thread_t * p_lpcmdec)
-{
-    intf_DbgMsg ( "LPCM Debug: requesting termination of lpcm decoder thread %p\n", p_lpcmdec );
-
-    /* Ask thread to kill itself */
-    p_lpcmdec->b_die = 1;
-
-    /* Make sure the decoder thread leaves the GetByte() function */
-    vlc_mutex_lock (&(p_lpcmdec->fifo.data_lock));
-    vlc_cond_signal (&(p_lpcmdec->fifo.data_wait));
-    vlc_mutex_unlock (&(p_lpcmdec->fifo.data_lock));
-
-    /* Waiting for the decoder thread to exit */
-    /* Remove this as soon as the "status" flag is implemented */
-    vlc_thread_join (p_lpcmdec->thread_id);
+    return p_lpcmdec->thread_id;
 }
 
 /* Following functions are local */
@@ -147,22 +116,20 @@ static int InitThread (lpcmdec_thread_t * p_lpcmdec)
 
     /* Our first job is to initialize the bit stream structure with the
      * beginning of the input stream */
-    vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
-    while (DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
+    vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
+    while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
         if (p_lpcmdec->b_die) {
-            vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
+            vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
             return -1;
         }
-        vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
+        vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
     }
-    p_lpcmdec->p_ts = DECODER_FIFO_START (p_lpcmdec->fifo)->p_first_ts;
+    p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
     byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
-    byte_stream->p_byte =
-       p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_start;
-    byte_stream->p_end =
-       p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_end;
+    byte_stream->p_byte = p_lpcmdec->p_data->p_payload_start;
+    byte_stream->p_end = p_lpcmdec->p_data->p_payload_end;
     byte_stream->info = p_lpcmdec;
-    vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
+    vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
 
     aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
     aout_fifo.i_channels = 2;
@@ -188,7 +155,8 @@ static void RunThread (lpcmdec_thread_t * p_lpcmdec)
 
     intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)\n", p_lpcmdec, getpid() );
 
-    msleep (INPUT_PTS_DELAY);
+    /* Fucking holy piece of shit ! */
+    //msleep (INPUT_PTS_DELAY);
 
     /* Initializing the lpcm decoder thread */
     if (InitThread (p_lpcmdec)) 
@@ -212,10 +180,10 @@ static void RunThread (lpcmdec_thread_t * p_lpcmdec)
             /* have to find a synchro point */
         }
     
-        if (DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts)
+        if (DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts)
         {
-               p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_lpcmdec->fifo)->i_pts;
-               DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts = 0;
+               p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
+               DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts = 0;
         }
         else
         {
@@ -258,22 +226,23 @@ static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
 {
     /* We take the lock, because we are going to read/write the start/end
      * indexes of the decoder fifo */
-    vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
+    vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
 
     /* Wait until a `die' order is sent */
     while (!p_lpcmdec->b_die) {
         /* Trash all received PES packets */
-        while (!DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
-            input_NetlistFreePES (p_lpcmdec->p_input, DECODER_FIFO_START(p_lpcmdec->fifo));
-            DECODER_FIFO_INCSTART (p_lpcmdec->fifo);
+        while (!DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
+            p_lpcmdec->p_fifo->pf_delete_pes(p_lpcmdec->p_fifo->p_packets_mgt,
+                    DECODER_FIFO_START(*p_lpcmdec->p_fifo));
+            DECODER_FIFO_INCSTART (*p_lpcmdec->p_fifo);
         }
 
         /* Waiting for the input thread to put new PES packets in the fifo */
-        vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
+        vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
     }
 
     /* We can release the lock before leaving */
-    vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
+    vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
 }
 
 /*****************************************************************************
similarity index 86%
rename from include/lpcm_decoder_thread.h
rename to src/lpcm_decoder/lpcm_decoder_thread.h
index afeaf02674e9ff21d8070d998a44c2c69f54e413..43905cca7cc70f0f9dfa8c4e5c53b8117858fb6d 100644 (file)
@@ -36,10 +36,10 @@ typedef struct lpcmdec_thread_s
     /*
      * Input properties
      */
-    decoder_fifo_t      fifo;                  /* stores the PES stream data */
-    input_thread_t *    p_input;
-    ts_packet_t *       p_ts;
-    int                        sync_ptr;       /* sync ptr from lpcm magic header */
+    decoder_fifo_t *    p_fifo;                /* stores the PES stream data */
+    data_packet_t *     p_data;
+    int                sync_ptr;         /* sync ptr from lpcm magic header */
+    adec_config_t *     p_config;
 
     /*
      * Decoder properties
@@ -58,5 +58,4 @@ typedef struct lpcmdec_thread_s
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
-lpcmdec_thread_t *      lpcmdec_CreateThread( input_thread_t * p_input );
-void                    lpcmdec_DestroyThread( lpcmdec_thread_t * p_lcpmdec );
+vlc_thread_t            lpcmdec_CreateThread( adec_config_t * p_config );
diff --git a/src/misc/decoder_fifo.c b/src/misc/decoder_fifo.c
deleted file mode 100644 (file)
index eae3330..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*****************************************************************************
- * decoder_fifo.c: auxiliaries functions used in decoder_fifo.h
- *****************************************************************************
- * Copyright (C) 1998, 1999, 2000 VideoLAN
- *
- * Authors: Michel Kaempf <maxx@via.ecp.fr>
- *
- * 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.
- *****************************************************************************/
-#include "defs.h"
-
-#include <sys/types.h>                        /* on BSD, uio.h needs types.h */
-#include <sys/uio.h>                                          /* for input.h */
-
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"
-
-#include "debug.h"                 /* XXX?? temporaire, requis par netlist.h */
-
-#include "input.h"
-#include "input_netlist.h"
-#include "decoder_fifo.h"
-
-void decoder_fifo_next( bit_stream_t * p_bit_stream )
-{
-    /* We are looking for the next TS packet that contains real data,
-     * and not just a PES header */
-    do
-    {
-        /* We were reading the last TS packet of this PES packet... It's
-         * time to jump to the next PES packet */
-        if ( p_bit_stream->p_ts->p_next_ts == NULL )
-        {
-            /* We are going to read/write the start and end indexes of the
-             * decoder fifo and to use the fifo's conditional variable,
-             * that's why we need to take the lock before */
-            vlc_mutex_lock( &p_bit_stream->p_decoder_fifo->data_lock );
-
-            /* Is the input thread dying ? */
-            if ( p_bit_stream->p_input->b_die )
-            {
-                vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
-                return;
-            }
-
-            /* We should increase the start index of the decoder fifo, but
-             * if we do this now, the input thread could overwrite the
-             * pointer to the current PES packet, and we weren't able to
-             * give it back to the netlist. That's why we free the PES
-             * packet first. */
-            input_NetlistFreePES( p_bit_stream->p_input, DECODER_FIFO_START(*p_bit_stream->p_decoder_fifo) );
-            DECODER_FIFO_INCSTART( *p_bit_stream->p_decoder_fifo );
-
-            while ( DECODER_FIFO_ISEMPTY(*p_bit_stream->p_decoder_fifo) )
-            {
-                vlc_cond_wait( &p_bit_stream->p_decoder_fifo->data_wait, &p_bit_stream->p_decoder_fifo->data_lock );
-                if ( p_bit_stream->p_input->b_die )
-                {
-                    vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
-                    return;
-                }
-            }
-
-            /* The next byte could be found in the next PES packet */
-            p_bit_stream->p_ts = DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->p_first_ts;
-
-            /* We can release the fifo's data lock */
-            vlc_mutex_unlock( &p_bit_stream->p_decoder_fifo->data_lock );
-        }
-        /* Perhaps the next TS packet of the current PES packet contains
-         * real data (ie its payload's size is greater than 0) */
-        else
-        {
-            p_bit_stream->p_ts = p_bit_stream->p_ts->p_next_ts;
-        }
-    } while ( p_bit_stream->p_ts->i_payload_start == p_bit_stream->p_ts->i_payload_end );
-
-    /* We've found a TS packet which contains interesting data... */
-    p_bit_stream->p_byte = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_start;
-    p_bit_stream->p_end = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_end;
-}
-
-void PeekNextPacket( bit_stream_t * p_bit_stream )
-{
-    WORD_TYPE   buffer_left;
-    int         i_bytes_left; /* FIXME : not portable in a 64bit environment */
-
-    /* Put the remaining bytes (not aligned on a word boundary) in a
-     * temporary buffer. */
-    i_bytes_left = p_bit_stream->p_end - p_bit_stream->p_byte;
-    buffer_left = *((WORD_TYPE *)p_bit_stream->p_end - 1);
-
-    /* We are looking for the next TS packet that contains real data,
-     * and not just a PES header */
-    do
-    {
-        /* We were reading the last TS packet of this PES packet... It's
-         * time to jump to the next PES packet */
-        if ( p_bit_stream->p_ts->p_next_ts == NULL )
-        {
-            /* We are going to read/write the start and end indexes of the
-             * decoder fifo and to use the fifo's conditional variable,
-             * that's why we need to take the lock before */
-            vlc_mutex_lock( &p_bit_stream->p_decoder_fifo->data_lock );
-
-            /* Is the input thread dying ? */
-            if ( p_bit_stream->p_input->b_die )
-            {
-                vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
-                return;
-            }
-
-            /* We should increase the start index of the decoder fifo, but
-             * if we do this now, the input thread could overwrite the
-             * pointer to the current PES packet, and we weren't able to
-             * give it back to the netlist. That's why we free the PES
-             * packet first. */
-            input_NetlistFreePES( p_bit_stream->p_input, DECODER_FIFO_START(*p_bit_stream->p_decoder_fifo) );
-            DECODER_FIFO_INCSTART( *p_bit_stream->p_decoder_fifo );
-
-            while ( DECODER_FIFO_ISEMPTY(*p_bit_stream->p_decoder_fifo) )
-            {
-                vlc_cond_wait( &p_bit_stream->p_decoder_fifo->data_wait, &p_bit_stream->p_decoder_fifo->data_lock );
-                if ( p_bit_stream->p_input->b_die )
-                {
-                    vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
-                    return;
-                }
-            }
-
-            /* The next byte could be found in the next PES packet */
-            p_bit_stream->p_ts = DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->p_first_ts;
-
-            /* We can release the fifo's data lock */
-            vlc_mutex_unlock( &p_bit_stream->p_decoder_fifo->data_lock );
-        }
-        /* Perhaps the next TS packet of the current PES packet contains
-         * real data (ie its payload's size is greater than 0) */
-        else
-        {
-            p_bit_stream->p_ts = p_bit_stream->p_ts->p_next_ts;
-        }
-    } while ( p_bit_stream->p_ts->i_payload_start == p_bit_stream->p_ts->i_payload_end );
-
-    /* We've found a TS packet which contains interesting data... */
-    p_bit_stream->p_byte = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_start;
-    p_bit_stream->p_end = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_end;
-
-    /* Copy remaining bits of the previous packet */
-    *((WORD_TYPE *)p_bit_stream->p_byte - 1) = buffer_left;
-    p_bit_stream->p_byte -= i_bytes_left;
-}
index c64c01c22fbaabb53cffba3600c46054d8e2eb02..5a8bae3052a77131b31286415dcf7db23b238444 100644 (file)
@@ -42,9 +42,8 @@
 #include "intf_msg.h"
 #include "debug.h"                                                 /* ASSERT */
 
-#include "input.h"
-#include "input_netlist.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
 
 #include "video.h"
 #include "video_output.h"
@@ -67,7 +66,7 @@ static void     EndThread           ( spudec_thread_t *p_spudec );
 /*****************************************************************************
  * spudec_CreateThread: create a spu decoder thread
  *****************************************************************************/
-spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
+vlc_thread_t spudec_CreateThread( vdec_config_t * p_config )
 {
     spudec_thread_t *     p_spudec;
 
@@ -77,7 +76,7 @@ spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
     if ( (p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) )) == NULL )
     {
         intf_ErrMsg("spudec error: not enough memory for spudec_CreateThread() to create the new thread\n");
-        return( NULL );
+        return( 0 );
     }
 
     /*
@@ -85,24 +84,11 @@ spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
      */
     p_spudec->b_die = 0;
     p_spudec->b_error = 0;
-
-    /*
-     * Initialize the input properties
-     */
-    /* Initialize the decoder fifo's data lock and conditional variable and set
-     * its buffer as empty */
-    vlc_mutex_init( &p_spudec->fifo.data_lock );
-    vlc_cond_init( &p_spudec->fifo.data_wait );
-    p_spudec->fifo.i_start = 0;
-    p_spudec->fifo.i_end = 0;
-    /* Initialize the bit stream structure */
-    p_spudec->bit_stream.p_input = p_input;
-    p_spudec->bit_stream.p_decoder_fifo = &p_spudec->fifo;
-    p_spudec->bit_stream.fifo.buffer = 0;
-    p_spudec->bit_stream.fifo.i_available = 0;
+    p_spudec->p_config = p_config;
+    p_spudec->p_fifo = p_config->decoder_config.p_decoder_fifo;
 
     /* Get the video output informations */
-    p_spudec->p_vout = p_input->p_vout;
+    p_spudec->p_vout = p_config->p_vout;
 
     /* Spawn the spu decoder thread */
     if ( vlc_thread_create(&p_spudec->thread_id, "spu decoder",
@@ -110,36 +96,11 @@ spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
     {
         intf_ErrMsg("spudec error: can't spawn spu decoder thread\n");
         free( p_spudec );
-        return( NULL );
+        return( 0 );
     }
 
     intf_DbgMsg("spudec debug: spu decoder thread (%p) created\n", p_spudec);
-    return( p_spudec );
-}
-
-/*****************************************************************************
- * spudec_DestroyThread: destroy a spu decoder thread
- *****************************************************************************
- * Destroy and terminate thread. This function will return 0 if the thread could
- * be destroyed, and non 0 else. The last case probably means that the thread
- * was still active, and another try may succeed.
- *****************************************************************************/
-void spudec_DestroyThread( spudec_thread_t *p_spudec )
-{
-    intf_DbgMsg( "spudec debug: requesting termination of "
-                 "spu decoder thread %p\n", p_spudec);
-
-    /* Ask thread to kill itself */
-    p_spudec->b_die = 1;
-
-    /* Warn the decoder that we're quitting */
-    vlc_mutex_lock( &p_spudec->fifo.data_lock );
-    vlc_cond_signal( &p_spudec->fifo.data_wait );
-    vlc_mutex_unlock( &p_spudec->fifo.data_lock );
-
-    /* Waiting for the decoder thread to exit */
-    /* Remove this as soon as the "status" flag is implemented */
-    vlc_thread_join( p_spudec->thread_id );
+    return( p_spudec->thread_id );
 }
 
 /* following functions are local */
@@ -155,23 +116,8 @@ static int InitThread( spudec_thread_t *p_spudec )
 {
     intf_DbgMsg("spudec debug: initializing spu decoder thread %p\n", p_spudec);
 
-    /* Our first job is to initialize the bit stream structure with the
-     * beginning of the input stream */
-    vlc_mutex_lock( &p_spudec->fifo.data_lock );
-    while ( DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
-    {
-        if ( p_spudec->b_die )
-        {
-            vlc_mutex_unlock( &p_spudec->fifo.data_lock );
-            return( 1 );
-        }
-        vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
-    }
-
-    p_spudec->bit_stream.p_ts = DECODER_FIFO_START( p_spudec->fifo )->p_first_ts;
-    p_spudec->bit_stream.p_byte = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_start;
-    p_spudec->bit_stream.p_end = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_end;
-    vlc_mutex_unlock( &p_spudec->fifo.data_lock );
+    p_spudec->p_config->decoder_config.pf_init_bit_stream( &p_spudec->bit_stream,
+            p_spudec->p_config->decoder_config.p_decoder_fifo );
 
     /* Mark thread as running and return */
     intf_DbgMsg( "spudec debug: InitThread(%p) succeeded\n", p_spudec );
@@ -211,7 +157,7 @@ static void RunThread( spudec_thread_t *p_spudec )
         unsigned char * p_spu_data;
         subpicture_t  * p_spu = NULL;
 
-        while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
+        while( !DECODER_FIFO_ISEMPTY(*p_spudec->p_fifo) )
         {
             /* wait for the next SPU ID.
              * XXX: We trash 0xff bytes since they probably come from
@@ -232,7 +178,7 @@ static void RunThread( spudec_thread_t *p_spudec )
             i_index = 2;
 
             /* get the useful PES size (real size - 10) */
-            i_pes_size = DECODER_FIFO_START(p_spudec->fifo)->i_pes_size - 9;
+            i_pes_size = DECODER_FIFO_START(*p_spudec->p_fifo)->i_pes_size - 9;
             i_pes_count = 1;
 
             /* the RLE stuff size */
@@ -249,7 +195,7 @@ static void RunThread( spudec_thread_t *p_spudec )
 
                 /* get display time */
                 p_spu->begin_date = p_spu->end_date
-                                = DECODER_FIFO_START(p_spudec->fifo)->i_pts;
+                                = DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts;
 
                 /* getting the RLE part */
                 while( i_index++ < i_rle_size )
@@ -357,11 +303,11 @@ static void RunThread( spudec_thread_t *p_spudec )
             {
                 /* Unexpected PES packet - trash it */
                 intf_ErrMsg( "spudec: trying to recover from bad packet\n" );
-                vlc_mutex_lock( &p_spudec->fifo.data_lock );
-                input_NetlistFreePES( p_spudec->bit_stream.p_input,
-                                      DECODER_FIFO_START(p_spudec->fifo) );
-                DECODER_FIFO_INCSTART( p_spudec->fifo );
-                vlc_mutex_unlock( &p_spudec->fifo.data_lock );
+                vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
+                p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
+                                      DECODER_FIFO_START(*p_spudec->p_fifo) );
+                DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
+                vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
             }
 
         }
@@ -392,24 +338,25 @@ static void ErrorThread( spudec_thread_t *p_spudec )
 {
     /* We take the lock, because we are going to read/write the start/end
      * indexes of the decoder fifo */
-    vlc_mutex_lock( &p_spudec->fifo.data_lock );
+    vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
 
     /* Wait until a `die' order is sent */
     while( !p_spudec->b_die )
     {
         /* Trash all received PES packets */
-        while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
+        while( !DECODER_FIFO_ISEMPTY(*p_spudec->p_fifo) )
         {
-            input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
-            DECODER_FIFO_INCSTART( p_spudec->fifo );
+            p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
+                    DECODER_FIFO_START(*p_spudec->p_fifo) );
+            DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
         }
 
         /* Waiting for the input thread to put new PES packets in the fifo */
-        vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
+        vlc_cond_wait( &p_spudec->p_fifo->data_wait, &p_spudec->p_fifo->data_lock );
     }
 
     /* We can release the lock before leaving */
-    vlc_mutex_unlock( &p_spudec->fifo.data_lock );
+    vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
 }
 
 /*****************************************************************************
similarity index 92%
rename from include/spu_decoder.h
rename to src/spu_decoder/spu_decoder.h
index 25c63773f1bdd25ff5c28f46f8000e1bb867532f..7069cc33254bccd9ab2a4ba7f2546a4922be483b 100644 (file)
@@ -37,9 +37,10 @@ typedef struct spudec_thread_s
     /*
      * Input properties
      */
-    decoder_fifo_t      fifo;                  /* stores the PES stream data */
+    decoder_fifo_t *    p_fifo;                /* stores the PES stream data */
     /* The bit stream structure handles the PES stream at the bit level */
     bit_stream_t        bit_stream;
+    vdec_config_t *     p_config;
 
     /*
      * Decoder properties
@@ -65,6 +66,5 @@ typedef struct spudec_thread_s
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
-spudec_thread_t *       spudec_CreateThread( input_thread_t * p_input );
-void                    spudec_DestroyThread( spudec_thread_t * p_spudec );
+vlc_thread_t       spudec_CreateThread( vdec_config_t * p_config );
 
index 061a29d3c745e99da44f3656691ce02ea9d212b8..6fbfe8789cf9489208c65d49e2b6afe468bc0325 100644 (file)
@@ -36,8 +36,9 @@
 
 #include "intf_msg.h"
 
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
index 29e05c4ede34941e6f9a6eb88ab9e3efb548321a..2fe220ac26a8b03d9d5e44ee373e53c1d0efe034 100644 (file)
@@ -38,8 +38,9 @@
 
 #include "intf_msg.h"
 
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
index d832004bbbb7bdccb122fa1a471db0b8252b55db..aea6c14f13facb0a091faaee5624c0991f4122b5 100644 (file)
@@ -38,8 +38,9 @@
 
 #include "intf_msg.h"
 
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
index 679994776263f8a178863ab1892bea457ef1a4e9..0951d3dcf40f3435d4c9f3da7b17e65a5e5f458a 100644 (file)
@@ -38,8 +38,9 @@
 
 #include "intf_msg.h"
 
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
index 9a3b5ae6f6920e83420289f30a63255a05f0bc57..3616832970aac9ed6f789cdef6a20478646ffe42 100644 (file)
@@ -39,8 +39,9 @@
 
 #include "intf_msg.h"
 
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
index 054fc2450c08ef71e0c58aa46ac4d9cea5bba0a1..16eaddb7fa93c6a846d7a0fde6cf9ece9f5c2dce 100644 (file)
@@ -37,9 +37,9 @@
 #include "intf_msg.h"
 #include "debug.h"                 /* XXX?? temporaire, requis par netlist.h */
 
-#include "input.h"
-#include "input_netlist.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
index b27c51e7c47096e17c82153269257d628a5bbd9c..6b7293d01b2e504bc357baf3cb0ff431268a50ec 100644 (file)
@@ -44,9 +44,9 @@
 #include "intf_msg.h"
 #include "debug.h"                 /* XXX?? temporaire, requis par netlist.h */
 
-#include "input.h"
-#include "input_netlist.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
@@ -63,7 +63,6 @@
 /*
  * Local prototypes
  */
-//static int      CheckConfiguration  ( video_cfg_t *p_cfg );
 static int      InitThread          ( vpar_thread_t *p_vpar );
 static void     RunThread           ( vpar_thread_t *p_vpar );
 static void     ErrorThread         ( vpar_thread_t *p_vpar );
@@ -77,12 +76,7 @@ static void     EndThread           ( vpar_thread_t *p_vpar );
  * Following configuration properties are used:
  * XXX??
  *****************************************************************************/
-#include "main.h"
-#include "interface.h"
-extern main_t *     p_main;
-
-vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
-                                   vout_thread_t *p_vout, int *pi_status */ )
+vlc_thread_t vpar_CreateThread( vdec_config_t * p_config )
 {
     vpar_thread_t *     p_vpar;
 
@@ -93,7 +87,7 @@ vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
     {
         intf_ErrMsg( "vpar error: not enough memory "
                      "for vpar_CreateThread() to create the new thread\n");
-        return( NULL );
+        return( 0 );
     }
 
     /*
@@ -101,24 +95,10 @@ vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
      */
     p_vpar->b_die = 0;
     p_vpar->b_error = 0;
+    p_vpar->p_fifo = p_config->decoder_config.p_decoder_fifo;
+    p_vpar->p_config = p_config;
 
-    /*
-     * Initialize the input properties
-     */
-    /* Initialize the decoder fifo's data lock and conditional variable
-     * and set its buffer as empty */
-    vlc_mutex_init( &p_vpar->fifo.data_lock );
-    vlc_cond_init( &p_vpar->fifo.data_wait );
-    p_vpar->fifo.i_start = 0;
-    p_vpar->fifo.i_end = 0;
-    /* Initialize the bit stream structure */
-    p_vpar->bit_stream.p_input = p_input;
-    p_vpar->bit_stream.p_decoder_fifo = &p_vpar->fifo;
-    p_vpar->bit_stream.fifo.buffer = 0;
-    p_vpar->bit_stream.fifo.i_available = 0;
-
-    /* FIXME !!!!?? */
-    p_vpar->p_vout = p_main->p_intf->p_vout;
+    p_vpar->p_vout = p_config->p_vout;
 
     /* Spawn the video parser thread */
     if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
@@ -126,54 +106,15 @@ vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
     {
         intf_ErrMsg("vpar error: can't spawn video parser thread\n");
         free( p_vpar );
-        return( NULL );
+        return( 0 );
     }
 
     intf_DbgMsg("vpar debug: video parser thread (%p) created\n", p_vpar);
-    return( p_vpar );
-}
-
-/*****************************************************************************
- * vpar_DestroyThread: destroy a generic parser thread
- *****************************************************************************
- * Destroy a terminated thread. This function will return 0 if the thread could
- * be destroyed, and non 0 else. The last case probably means that the thread
- * was still active, and another try may succeed.
- *****************************************************************************/
-void vpar_DestroyThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
-{
-    intf_DbgMsg( "vpar debug: requesting termination of "
-                 "video parser thread %p\n", p_vpar);
-
-    /* Ask thread to kill itself */
-    p_vpar->b_die = 1;
-    /* Make sure the parser thread leaves the GetByte() function */
-    vlc_mutex_lock( &(p_vpar->fifo.data_lock) );
-    vlc_cond_signal( &(p_vpar->fifo.data_wait) );
-    vlc_mutex_unlock( &(p_vpar->fifo.data_lock) );
-
-    /* Waiting for the parser thread to exit */
-    /* Remove this as soon as the "status" flag is implemented */
-    vlc_thread_join( p_vpar->thread_id );
+    return( p_vpar->thread_id );
 }
 
 /* following functions are local */
 
-/*****************************************************************************
- * CheckConfiguration: check vpar_CreateThread() configuration
- *****************************************************************************
- * Set default parameters where required. In DEBUG mode, check if configuration
- * is valid.
- *****************************************************************************/
-#if 0
-static int CheckConfiguration( video_cfg_t *p_cfg )
-{
-    /* XXX?? */
-
-    return( 0 );
-}
-#endif
-
 /*****************************************************************************
  * InitThread: initialize vpar output thread
  *****************************************************************************
@@ -189,24 +130,8 @@ static int InitThread( vpar_thread_t *p_vpar )
 
     intf_DbgMsg("vpar debug: initializing video parser thread %p\n", p_vpar);
 
-    /* Our first job is to initialize the bit stream structure with the
-     * beginning of the input stream */
-    vlc_mutex_lock( &p_vpar->fifo.data_lock );
-    while ( DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
-    {
-        if ( p_vpar->b_die )
-        {
-            vlc_mutex_unlock( &p_vpar->fifo.data_lock );
-            return( 1 );
-        }
-        vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
-    }
-    p_vpar->bit_stream.p_ts = DECODER_FIFO_START( p_vpar->fifo )->p_first_ts;
-    p_vpar->bit_stream.p_byte = p_vpar->bit_stream.p_ts->buffer
-                                + p_vpar->bit_stream.p_ts->i_payload_start;
-    p_vpar->bit_stream.p_end = p_vpar->bit_stream.p_ts->buffer
-                               + p_vpar->bit_stream.p_ts->i_payload_end;
-    vlc_mutex_unlock( &p_vpar->fifo.data_lock );
+    p_vpar->p_config->decoder_config.pf_init_bit_stream( &p_vpar->bit_stream,
+        p_vpar->p_config->decoder_config.p_decoder_fifo );
 
     /* Initialize parsing data */
     p_vpar->sequence.p_forward = NULL;
@@ -310,12 +235,12 @@ static void RunThread( vpar_thread_t *p_vpar )
      * Main loop - it is not executed if an error occured during
      * initialization
      */
-    while( (!p_vpar->b_die) && (!p_vpar->b_error) )
+    while( (!p_vpar->p_fifo->b_die) && (!p_vpar->b_error) )
     {
         /* Find the next sequence header in the stream */
         p_vpar->b_error = vpar_NextSequenceHeader( p_vpar );
 
-        while( (!p_vpar->b_die) && (!p_vpar->b_error) )
+        while( (!p_vpar->p_fifo->b_die) && (!p_vpar->b_error) )
         {
 #ifdef STATS
             p_vpar->c_loops++;
@@ -354,25 +279,25 @@ static void ErrorThread( vpar_thread_t *p_vpar )
 {
     /* We take the lock, because we are going to read/write the start/end
      * indexes of the decoder fifo */
-    vlc_mutex_lock( &p_vpar->fifo.data_lock );
+    vlc_mutex_lock( &p_vpar->p_fifo->data_lock );
 
     /* Wait until a `die' order is sent */
-    while( !p_vpar->b_die )
+    while( !p_vpar->p_fifo->b_die )
     {
         /* Trash all received PES packets */
-        while( !DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
+        while( !DECODER_FIFO_ISEMPTY(*p_vpar->p_fifo) )
         {
-            input_NetlistFreePES( p_vpar->bit_stream.p_input,
-                                  DECODER_FIFO_START(p_vpar->fifo) );
-            DECODER_FIFO_INCSTART( p_vpar->fifo );
+            p_vpar->p_fifo->pf_delete_pes( p_vpar->p_fifo->p_packets_mgt,
+                                  DECODER_FIFO_START(*p_vpar->p_fifo) );
+            DECODER_FIFO_INCSTART( *p_vpar->p_fifo );
         }
 
         /* Waiting for the input thread to put new PES packets in the fifo */
-        vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
+        vlc_cond_wait( &p_vpar->p_fifo->data_wait, &p_vpar->p_fifo->data_lock );
     }
 
     /* We can release the lock before leaving */
-    vlc_mutex_unlock( &p_vpar->fifo.data_lock );
+    vlc_mutex_unlock( &p_vpar->p_fifo->data_lock );
 }
 
 /*****************************************************************************
index 75926fdb15a90f7730d172b79efc2ae06bc90af9..59572922deaae690723caa74a4e3633859ea10b4 100644 (file)
@@ -40,9 +40,9 @@
 #include "intf_msg.h"
 #include "debug.h"                 /* XXX?? temporaire, requis par netlist.h */
 
-#include "input.h"
-#include "input_netlist.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
@@ -652,7 +652,7 @@ static __inline__ void DecodeMPEG1NonIntra( vpar_thread_t * p_vpar,
     i_coef = 0;
     b_sign = 0;
 
-    for( i_parse = 0; !p_vpar->b_die; i_parse++ )
+    for( i_parse = 0; !p_vpar->p_fifo->b_die; i_parse++ )
     {
         i_code = ShowBits( &p_vpar->bit_stream, 16 );
         if( i_code >= 16384 )
@@ -810,7 +810,7 @@ static __inline__ void DecodeMPEG1Intra( vpar_thread_t * p_vpar,
     i_coef = 0;
     b_sign = 0;
 
-    for( i_parse = 1; !p_vpar->b_die/*i_parse < 64*/; i_parse++ )
+    for( i_parse = 1; !p_vpar->p_fifo->b_die/*i_parse < 64*/; i_parse++ )
     {
         i_code = ShowBits( &p_vpar->bit_stream, 16 );
         /* We use 2 main tables for the coefficients */
@@ -932,7 +932,7 @@ static __inline__ void DecodeMPEG2NonIntra( vpar_thread_t * p_vpar,
 
     i_nc = 0;
     i_coef = 0;
-    for( i_parse = 0; !p_vpar->b_die; i_parse++ )
+    for( i_parse = 0; !p_vpar->p_fifo->b_die; i_parse++ )
     {
         i_code = ShowBits( &p_vpar->bit_stream, 16 );
         if( i_code >= 16384 )
@@ -1078,7 +1078,7 @@ static __inline__ void DecodeMPEG2Intra( vpar_thread_t * p_vpar,
 
     i_coef = 0;
     b_vlc_intra = p_vpar->picture.b_intra_vlc_format;
-    for( i_parse = 1; !p_vpar->b_die/*i_parse < 64*/; i_parse++ )
+    for( i_parse = 1; !p_vpar->p_fifo->b_die/*i_parse < 64*/; i_parse++ )
     {
         i_code = ShowBits( &p_vpar->bit_stream, 16 );
         /* We use 2 main tables for the coefficients */
@@ -2283,8 +2283,9 @@ static __inline__ void SliceHeader( vpar_thread_t * p_vpar,
             return;
         }
     }
-    while( ShowBits( &p_vpar->bit_stream, 23 ) && !p_vpar->b_die );
-    NextStartCode( p_vpar );
+    while( ShowBits( &p_vpar->bit_stream, 23 )
+            && !p_vpar->p_fifo->b_die );
+    NextStartCode( &p_vpar->bit_stream );
 }
 
 /*****************************************************************************
@@ -2295,13 +2296,13 @@ void vpar_PictureData( vpar_thread_t * p_vpar, int i_mb_base )
     int         i_mb_address = 0;
     u32         i_dummy;
 
-    NextStartCode( p_vpar );
+    NextStartCode( &p_vpar->bit_stream );
     while( ((p_vpar->picture.i_coding_type != I_CODING_TYPE
                     && p_vpar->picture.i_coding_type != D_CODING_TYPE)
              || !p_vpar->picture.b_error)
            && i_mb_address < (p_vpar->sequence.i_mb_size
                     >> (p_vpar->picture.i_structure != FRAME_STRUCTURE))
-           && !p_vpar->b_die )
+           && !p_vpar->p_fifo->b_die )
     {
         if( ((i_dummy = ShowBits( &p_vpar->bit_stream, 32 ))
                  < SLICE_START_CODE_MIN) ||
index 3616e48b042b5a99136d78bf07cc38e4510eba8a..4cf469ad5389445ab2f57331912d453d414d45fa 100644 (file)
@@ -38,8 +38,9 @@
 
 #include "intf_msg.h"
 
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
@@ -56,7 +57,7 @@
 /*
  * Local prototypes
  */
-static __inline__ void NextStartCode( vpar_thread_t * p_vpar );
+static __inline__ void NextStartCode( bit_stream_t * );
 static void SequenceHeader( vpar_thread_t * p_vpar );
 static void GroupHeader( vpar_thread_t * p_vpar );
 static void PictureHeader( vpar_thread_t * p_vpar );
@@ -264,9 +265,9 @@ static __inline__ void LinkMatrix( quant_matrix_t * p_matrix, int * pi_array )
  *****************************************************************************/
 int vpar_NextSequenceHeader( vpar_thread_t * p_vpar )
 {
-    while( !p_vpar->b_die )
+    while( !p_vpar->p_fifo->b_die )
     {
-        NextStartCode( p_vpar );
+        NextStartCode( &p_vpar->bit_stream );
         if( ShowBits( &p_vpar->bit_stream, 32 ) == SEQUENCE_HEADER_CODE )
         {
             return 0;
@@ -281,9 +282,9 @@ int vpar_NextSequenceHeader( vpar_thread_t * p_vpar )
  *****************************************************************************/
 int vpar_ParseHeader( vpar_thread_t * p_vpar )
 {
-    while( !p_vpar->b_die )
+    while( !p_vpar->p_fifo->b_die )
     {
-        NextStartCode( p_vpar );
+        NextStartCode( &p_vpar->bit_stream );
         switch( GetBits32( &p_vpar->bit_stream ) )
         {
         case SEQUENCE_HEADER_CODE:
@@ -389,7 +390,7 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
     /*
      * Sequence Extension
      */
-    NextStartCode( p_vpar );
+    NextStartCode( &p_vpar->bit_stream );
     if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
     {
         int                         i_dummy;
@@ -520,7 +521,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
     /*
      * Picture Coding Extension
      */
-    NextStartCode( p_vpar );
+    NextStartCode( &p_vpar->bit_stream );
     if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
     {
         /* Parse picture_coding_extension */
@@ -673,7 +674,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
              == NULL )
         {
             intf_DbgMsg("vpar debug: allocation error in vout_CreatePicture, delaying\n");
-            if( p_vpar->b_die || p_vpar->b_error )
+            if( p_vpar->p_fifo->b_die || p_vpar->b_error )
             {
                 return;
             }
@@ -736,7 +737,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
 
     vpar_PictureData( p_vpar, i_mb_base );
 
-    if( p_vpar->b_die || p_vpar->b_error )
+    if( p_vpar->p_fifo->b_die || p_vpar->b_error )
     {
         return;
     }
@@ -797,9 +798,9 @@ static void PictureHeader( vpar_thread_t * p_vpar )
  *****************************************************************************/
 static void ExtensionAndUserData( vpar_thread_t * p_vpar )
 {
-    while( !p_vpar->b_die )
+    while( !p_vpar->p_fifo->b_die )
     {
-        NextStartCode( p_vpar );
+        NextStartCode( &p_vpar->bit_stream );
         switch( ShowBits( &p_vpar->bit_stream, 32 ) )
         {
         case EXTENSION_START_CODE:
index 6d4a886a3b4d5ba332509c5715e3a6b9d1e4ec30..d74ee36a3fdc104f23a8c58b5bc1769536ef991b 100644 (file)
 
 #include "intf_msg.h"
 
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
 #include "video.h"
 #include "video_output.h"
 
@@ -151,7 +152,7 @@ void vpar_SynchroInit( vpar_thread_t * p_vpar )
     memset( p_vpar->synchro.p_tau, 0, 4 * sizeof(mtime_t) );
     memset( p_vpar->synchro.pi_meaningful, 0, 4 * sizeof(unsigned int) );
     p_vpar->synchro.b_dropped_last = 0;
-    p_vpar->synchro.current_pts = mdate() + INPUT_PTS_DELAY;
+    p_vpar->synchro.current_pts = mdate() + DEFAULT_PTS_DELAY;
     p_vpar->synchro.backward_pts = 0;
 }