Commit d5b04453 authored by Christophe Massiot's avatar Christophe Massiot

STABLE/HEAD merge ; backported the Next Generation Buffer Manager.

parent f6b7894d
...@@ -110,7 +110,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \ ...@@ -110,7 +110,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
# C Objects # C Objects
# #
INTERFACE := main interface intf_msg intf_playlist intf_channels INTERFACE := main interface intf_msg intf_playlist intf_channels
INPUT := input input_ext-dec input_ext-intf input_dec input_programs input_netlist input_clock mpeg_system INPUT := input input_ext-dec input_ext-intf input_dec input_programs input_clock mpeg_system
VIDEO_OUTPUT := video_output video_text video_spu video_yuv VIDEO_OUTPUT := video_output video_text video_spu video_yuv
AUDIO_OUTPUT := audio_output aout_ext-dec aout_u8 aout_s8 aout_u16 aout_s16 aout_spdif AUDIO_OUTPUT := audio_output aout_ext-dec aout_u8 aout_s8 aout_u16 aout_s16 aout_spdif
MISC := mtime tests modules netutils iso_lang MISC := mtime tests modules netutils iso_lang
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions * Collection of useful common types and macros definitions
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: common.h,v 1.53.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: common.h,v 1.53.2.2 2001/12/31 01:21:44 massiot Exp $
* *
* Authors: Samuel Hocevar <sam@via.ecp.fr> * Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr> * Vincent Seguin <seguin@via.ecp.fr>
...@@ -347,18 +347,6 @@ typedef struct module_symbols_s ...@@ -347,18 +347,6 @@ typedef struct module_symbols_s
struct pgrm_descriptor_s *, struct pgrm_descriptor_s *,
mtime_t ); mtime_t );
int ( * input_NetlistInit ) ( struct input_thread_s *,
int, int, int, size_t, int );
struct iovec * ( * input_NetlistGetiovec ) ( void * p_method_data );
void ( * input_NetlistMviovec ) ( void * , int,
struct data_packet_s **);
struct data_packet_s * ( * input_NetlistNewPacket ) ( void *, size_t );
struct data_packet_s * ( * input_NetlistNewPtr ) ( void * );
struct pes_packet_s * ( * input_NetlistNewPES ) ( void * );
void ( * input_NetlistDeletePacket ) ( void *, struct data_packet_s * );
void ( * input_NetlistDeletePES ) ( void *, struct pes_packet_s * );
void ( * input_NetlistEnd ) ( struct input_thread_s * );
struct aout_fifo_s * ( * aout_CreateFifo ) struct aout_fifo_s * ( * aout_CreateFifo )
( int, int, long, long, long, void * ); ( int, int, long, long, long, void * );
void ( * aout_DestroyFifo ) ( struct aout_fifo_s * ); void ( * aout_DestroyFifo ) ( struct aout_fifo_s * );
......
...@@ -97,13 +97,6 @@ ...@@ -97,13 +97,6 @@
/* Environment variable containing the memcpy method */ /* Environment variable containing the memcpy method */
#define MEMCPY_METHOD_VAR "vlc_memcpy" #define MEMCPY_METHOD_VAR "vlc_memcpy"
/*
* Decoders FIFO configuration
*/
/* Size of the FIFO. FIFO_SIZE+1 must be a power of 2 */
#define FIFO_SIZE 1023
/* /*
* Paths * Paths
*/ */
...@@ -175,6 +168,9 @@ ...@@ -175,6 +168,9 @@
/* Maximum length of a hostname or source name */ /* Maximum length of a hostname or source name */
#define INPUT_MAX_SOURCE_LENGTH 100 #define INPUT_MAX_SOURCE_LENGTH 100
/* Maximum memory the input is allowed to use (20 MB) */
#define INPUT_MAX_ALLOCATION 20971520
/* Default network protocol */ /* Default network protocol */
#define INPUT_NETWORK_PROTOCOL_VAR "vlc_network_protocol" #define INPUT_NETWORK_PROTOCOL_VAR "vlc_network_protocol"
#define INPUT_NETWORK_PROTOCOL_DEFAULT "ts" #define INPUT_NETWORK_PROTOCOL_DEFAULT "ts"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders * input_ext-dec.h: structures exported to the VideoLAN decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-dec.h,v 1.41.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: input_ext-dec.h,v 1.41.2.2 2001/12/31 01:21:44 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Kaempf <maxx@via.ecp.fr> * Michel Kaempf <maxx@via.ecp.fr>
...@@ -40,22 +40,25 @@ ...@@ -40,22 +40,25 @@
***************************************************************************** *****************************************************************************
* Describe a data packet. * Describe a data packet.
*****************************************************************************/ *****************************************************************************/
#define DATA_PACKET \
/* start of the PS or TS packet */ \
byte_t * p_demux_start; \
/* start of the PES payload in this packet */ \
byte_t * p_payload_start; \
byte_t * p_payload_end; /* guess ? :-) */ \
/* is the packet messed up ? */ \
boolean_t b_discard_payload;
typedef struct data_packet_s typedef struct data_packet_s
{ {
/* Nothing before this line, the code relies on that */ /* Used to chain the packets that carry data for a same PES or PSI */
byte_t * p_buffer; /* raw data packet */ struct data_packet_s * p_next;
long l_size; /* buffer size */
/* 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 ? */
int * pi_refcount; DATA_PACKET
/* Used to chain the TS packets that carry data for a same PES or PSI */ /* Please note that at least one buffer allocator (in particular, the
struct data_packet_s * p_next; * Next Generation Buffer Allocator) extends this structure with
* private data after DATA_PACKET. */
} data_packet_t; } data_packet_t;
/***************************************************************************** /*****************************************************************************
...@@ -66,6 +69,9 @@ typedef struct data_packet_s ...@@ -66,6 +69,9 @@ typedef struct data_packet_s
*****************************************************************************/ *****************************************************************************/
typedef struct pes_packet_s typedef struct pes_packet_s
{ {
/* Chained list to the next PES packet (depending on the context) */
struct pes_packet_s * p_next;
/* PES properties */ /* PES properties */
boolean_t b_data_alignment; /* used to find the beginning of boolean_t b_data_alignment; /* used to find the beginning of
* a video or audio unit */ * a video or audio unit */
...@@ -77,12 +83,15 @@ typedef struct pes_packet_s ...@@ -77,12 +83,15 @@ typedef struct pes_packet_s
int i_rate; /* current pace of reading int i_rate; /* current pace of reading
* (see stream_control.h) */ * (see stream_control.h) */
int i_pes_size; /* size of the current PES packet */ unsigned int i_pes_size; /* size of the current PES packet */
/* Pointers to packets (packets are then linked by the p_prev and /* Chained list to packets */
p_next fields of the data_packet_t struct) */
data_packet_t * p_first; /* The first packet contained by this data_packet_t * p_first; /* The first packet contained by this
* PES (used by decoders). */ * PES (used by decoders). */
data_packet_t * p_last; /* The last packet contained by this
PES (used by the buffer allocator) */
unsigned int i_nb_data; /* Number of data packets in the chained
list */
} pes_packet_t; } pes_packet_t;
/***************************************************************************** /*****************************************************************************
...@@ -97,9 +106,9 @@ typedef struct decoder_fifo_s ...@@ -97,9 +106,9 @@ typedef struct decoder_fifo_s
vlc_cond_t data_wait; /* fifo data conditional variable */ vlc_cond_t data_wait; /* fifo data conditional variable */
/* Data */ /* Data */
pes_packet_t * buffer[FIFO_SIZE + 1]; pes_packet_t * p_first;
int i_start; pes_packet_t ** pp_last;
int i_end; int i_depth; /* number of PES packets in the stack */
/* Communication interface between input and decoders */ /* Communication interface between input and decoders */
boolean_t b_die; /* the decoder should return now */ boolean_t b_die; /* the decoder should return now */
...@@ -110,18 +119,6 @@ typedef struct decoder_fifo_s ...@@ -110,18 +119,6 @@ typedef struct decoder_fifo_s
/* function to use when releasing a PES */ /* function to use when releasing a PES */
} decoder_fifo_t; } 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 * bit_fifo_t : bit fifo descriptor
***************************************************************************** *****************************************************************************
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* control the pace of reading. * control the pace of reading.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.51 2001/12/07 16:47:47 jobi Exp $ * $Id: input_ext-intf.h,v 1.51.2.1 2001/12/31 01:21:44 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
/* /*
* Communication input -> interface * Communication input -> interface
*/ */
#define INPUT_MAX_PLUGINS 1
/* FIXME ! */ /* FIXME ! */
#define REQUESTED_MPEG 1 #define REQUESTED_MPEG 1
#define REQUESTED_AC3 2 #define REQUESTED_AC3 2
...@@ -66,7 +65,6 @@ typedef struct es_descriptor_s ...@@ -66,7 +65,6 @@ typedef struct es_descriptor_s
/* PES parser information */ /* PES parser information */
struct pes_packet_s * p_pes; /* Current PES */ 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 */ int i_pes_real_size; /* as indicated by the header */
/* Decoder information */ /* Decoder information */
...@@ -95,6 +93,7 @@ typedef struct es_descriptor_s ...@@ -95,6 +93,7 @@ typedef struct es_descriptor_s
#define SPU_ES 0x02 #define SPU_ES 0x02
#define NAV_ES 0x03 #define NAV_ES 0x03
#define UNKNOWN_ES 0xFF #define UNKNOWN_ES 0xFF
/***************************************************************************** /*****************************************************************************
* pgrm_descriptor_t * pgrm_descriptor_t
***************************************************************************** *****************************************************************************
...@@ -263,7 +262,7 @@ typedef struct input_thread_s ...@@ -263,7 +262,7 @@ typedef struct input_thread_s
/* Read & Demultiplex */ /* Read & Demultiplex */
int (* pf_read)( struct input_thread_s *, int (* pf_read)( struct input_thread_s *,
struct data_packet_s * pp_packets[] ); struct data_packet_s ** );
void (* pf_demux)( struct input_thread_s *, void (* pf_demux)( struct input_thread_s *,
struct data_packet_s * ); struct data_packet_s * );
...@@ -289,8 +288,6 @@ typedef struct input_thread_s ...@@ -289,8 +288,6 @@ typedef struct input_thread_s
int i_handle; /* socket or file descriptor */ int i_handle; /* socket or file descriptor */
FILE * p_stream; /* if applicable */ FILE * p_stream; /* if applicable */
void * p_handle; /* if i_handle isn't suitable */ void * p_handle; /* if i_handle isn't suitable */
int i_read_once; /* number of packet read by
* pf_read once */
void * p_method_data; /* data of the packet manager */ void * p_method_data; /* data of the packet manager */
void * p_plugin_data; /* data of the plugin */ void * p_plugin_data; /* data of the plugin */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* but exported to plug-ins * but exported to plug-ins
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: input_ext-plugins.h,v 1.7 2001/12/07 16:47:47 jobi Exp $ * $Id: input_ext-plugins.h,v 1.7.2.1 2001/12/31 01:21:44 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -27,10 +27,6 @@ ...@@ -27,10 +27,6 @@
*/ */
/* FIXME: you've gotta move this move this, you've gotta move this move this */ /* FIXME: you've gotta move this move this, you've gotta move this move this */
#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. */
#define PADDING_PACKET_SIZE 188 /* Size of the NULL packet inserted in case #define PADDING_PACKET_SIZE 188 /* Size of the NULL packet inserted in case
* of data loss (this should be < 188). */ * of data loss (this should be < 188). */
#define PADDING_PACKET_NUMBER 10 /* Number of padding packets top insert to #define PADDING_PACKET_NUMBER 10 /* Number of padding packets top insert to
...@@ -115,15 +111,16 @@ static __inline__ void input_NullPacket( input_thread_t * p_input, ...@@ -115,15 +111,16 @@ static __inline__ void input_NullPacket( input_thread_t * p_input,
return; return;
} }
memset( p_pad_data->p_buffer, 0, PADDING_PACKET_SIZE ); memset( p_pad_data->p_payload_start, 0, PADDING_PACKET_SIZE );
p_pad_data->b_discard_payload = 1; p_pad_data->b_discard_payload = 1;
p_pes = p_es->p_pes; p_pes = p_es->p_pes;
if( p_pes != NULL ) if( p_pes != NULL )
{ {
p_pes->b_discontinuity = 1; p_pes->b_discontinuity = 1;
p_es->p_last->p_next = p_pad_data; p_pes->p_last->p_next = p_pad_data;
p_es->p_last = p_pad_data; p_pes->p_last = p_pad_data;
p_pes->i_nb_data++;
} }
else else
{ {
...@@ -135,7 +132,8 @@ static __inline__ void input_NullPacket( input_thread_t * p_input, ...@@ -135,7 +132,8 @@ static __inline__ void input_NullPacket( input_thread_t * p_input,
} }
p_pes->i_rate = p_input->stream.control.i_rate; p_pes->i_rate = p_input->stream.control.i_rate;
p_pes->p_first = p_pad_data; p_pes->p_first = p_pes->p_last = p_pad_data;
p_pes->i_nb_data = 1;
p_pes->b_discontinuity = 1; p_pes->b_discontinuity = 1;
input_DecodePES( p_es->p_decoder_fifo, p_pes ); input_DecodePES( p_es->p_decoder_fifo, p_pes );
} }
...@@ -143,68 +141,680 @@ static __inline__ void input_NullPacket( input_thread_t * p_input, ...@@ -143,68 +141,680 @@ static __inline__ void input_NullPacket( input_thread_t * p_input,
/* /*
* Optional netlist management * Optional Next Generation buffer manager
*
* Either buffers can only be used in one data packet (PS case), or buffers
* contain several data packets (DVD case). In the first case, buffers are
* embedded into data packets, otherwise they are allocated separately and
* shared with a refcount. --Meuuh
*/ */
/* Number of buffers for the calculation of the mean */
#define INPUT_BRESENHAM_NB 50
/* Flags */
#define BUFFERS_NOFLAGS 0
#define BUFFERS_UNIQUE_SIZE 1 /* Only with NB_LIFO == 1 */
/***************************************************************************** /*****************************************************************************
* netlist_t: structure to manage a netlist * _input_buffers_t: defines a LIFO per data type to keep
*****************************************************************************/ *****************************************************************************/
typedef struct netlist_s #define PACKETS_LIFO( TYPE, NAME ) \
struct \
{ \
TYPE * p_stack; \
unsigned int i_depth; \
} NAME;
#define BUFFERS_LIFO( TYPE, NAME ) \
struct \
{ \
TYPE * p_stack; /* First item in the LIFO */ \
unsigned int i_depth; /* Number of items in the LIFO */ \
unsigned int i_average_size; /* Average size of the items (Bresenham) */\
} NAME;
#define DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO ) \
typedef struct _input_buffers_s \
{ \
vlc_mutex_t lock; \
PACKETS_LIFO( pes_packet_t, pes ) \
BUFFERS_LIFO( _data_packet_t, data[NB_LIFO] ) \
size_t i_allocated; \
} _input_buffers_t;
#define DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ) \
typedef struct _input_buffers_s \
{ \
vlc_mutex_t lock; \
PACKETS_LIFO( pes_packet_t, pes ) \
PACKETS_LIFO( _data_packet_t, data ) \
BUFFERS_LIFO( _data_buffer_t, buffers[NB_LIFO] ) \
size_t i_allocated; \
} _input_buffers_t;
/* Data buffer, used in case the buffer can be shared between several data
* packets */
typedef struct _data_buffer_s
{ {
vlc_mutex_t lock; struct _data_buffer_s * p_next;
size_t i_buffer_size; /* number of data packets this buffer is referenced from - when it falls
* down to 0, the buffer is freed */
int i_refcount;
/* Buffers */ struct /* for compatibility with _data_packet_t */
byte_t * p_buffers; /* Big malloc'ed area */ {
data_packet_t * p_data; /* malloc'ed area */ /* size of the current buffer (starting right thereafter) */
pes_packet_t * p_pes; /* malloc'ed area */ unsigned int i_size;
} _private;
} _data_buffer_t;
/* FIFOs of free packets */ /* We overload the data_packet_t type to add private members */
data_packet_t ** pp_free_data; typedef struct _data_packet_s
pes_packet_t ** pp_free_pes; {
struct iovec * p_free_iovec; struct _data_packet_s * p_next;
/* FIFO size */
unsigned int i_nb_iovec;
unsigned int i_nb_pes;
unsigned int i_nb_data;
/* Index */ DATA_PACKET
unsigned int i_iovec_start, i_iovec_end;
unsigned int i_data_start, i_data_end;
unsigned int i_pes_start, i_pes_end;
/* Reference counters for iovec */ union
unsigned int * pi_refcount; {
struct _data_buffer_s * p_buffer; /* in case of shared buffers */
/* size of the embedded buffer (starting right thereafter) */
unsigned int i_size;
} _private;
} _data_packet_t;
/* Number of blocs read once by readv */
unsigned int i_read_once;
} netlist_t;
/***************************************************************************** /*****************************************************************************
* Prototypes * input_BuffersInit: initialize the cache structures, return a pointer to it
*****************************************************************************/ *****************************************************************************/
#ifndef PLUGIN #define DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO ) \
int input_NetlistInit( struct input_thread_s *, static void * input_BuffersInit( void ) \
int i_nb_iovec, { \
int i_nb_data, _input_buffers_t * p_buffers = malloc( sizeof( _input_buffers_t ) ); \
int i_nb_pes, \
size_t i_buffer_size, if( p_buffers == NULL ) \
int i_read_once ); { \
return( NULL ); \
struct iovec * input_NetlistGetiovec( void * p_method_data ); } \
void input_NetlistMviovec( void * , int, \
struct data_packet_s **); memset( p_buffers, 0, sizeof( _input_buffers_t ) ); \
struct data_packet_s * input_NetlistNewPtr( void * ); vlc_mutex_init( &p_buffers->lock ); \
struct data_packet_s * input_NetlistNewPacket( void *, size_t ); \
struct pes_packet_s * input_NetlistNewPES( void * ); return (void *)p_buffers; \
void input_NetlistDeletePacket( void *, }
struct data_packet_s * );
void input_NetlistDeletePES( void *, /*****************************************************************************
struct pes_packet_s * ); * input_BuffersEnd: free all cached structures
void input_NetlistEnd( struct input_thread_s * ); *****************************************************************************/
#endif #define BUFFERS_END_STAT_BUFFERS_LOOP( STRUCT ) \
for( i = 0; i < NB_LIFO; i++ ) \
{ \
if( FLAGS & BUFFERS_UNIQUE_SIZE ) \
{ \
intf_StatMsg( \
"input buffers stats: " #STRUCT "[%d]: %d packets", \
i, p_buffers->STRUCT[i].i_depth ); \
} \
else \
{ \
intf_StatMsg( \
"input buffers stats: " #STRUCT "[%d]: %d bytes, %d packets", \
i, p_buffers->STRUCT[i].i_average_size, \
p_buffers->STRUCT[i].i_depth ); \
} \
}
#define BUFFERS_END_STAT( FLAGS, NB_LIFO ) \
BUFFERS_END_STAT_BUFFERS_LOOP( data );
#define BUFFERS_END_STAT_SHARED( FLAGS, NB_LIFO ) \
intf_StatMsg( "input buffers stats: data: %d packets", \
p_buffers->data.i_depth ); \
BUFFERS_END_STAT_BUFFERS_LOOP( buffers );
#define BUFFERS_END_BUFFERS_LOOP \
while( p_buf != NULL ) \
{ \
p_next = p_buf->p_next; \
p_buffers->i_allocated -= p_buf->_private.i_size; \
free( p_buf ); \
p_buf = p_next; \
}
#define BUFFERS_END_PACKETS_LOOP \
while( p_packet != NULL ) \
{ \
p_next = p_packet->p_next; \
free( p_packet ); \
p_packet = p_next; \
}
#define BUFFERS_END_LOOP( FLAGS, NB_LIFO ) \
for( i = 0; i < NB_LIFO; i++ ) \
{ \
_data_packet_t * p_next; \
_data_packet_t * p_buf = p_buffers->data[i].p_stack; \
BUFFERS_END_BUFFERS_LOOP; \
} \
#define BUFFERS_END_LOOP_SHARED( FLAGS, NB_LIFO ) \
{ \
/* Free data packets */ \
_data_packet_t * p_next; \
_data_packet_t * p_packet = p_buffers->data.p_stack; \
BUFFERS_END_PACKETS_LOOP; \
} \
\
for( i = 0; i < NB_LIFO; i++ ) \
{ \
_data_buffer_t * p_next; \
_data_buffer_t * p_buf = p_buffers->buffers[i].p_stack; \
BUFFERS_END_BUFFERS_LOOP; \
} \
#define BUFFERS_END( FLAGS, NB_LIFO, STAT_LOOP, LOOP ) \
static void input_BuffersEnd( void * _p_buffers ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
\
if( _p_buffers != NULL ) \
{ \
int i; \
\
if( p_main->b_stats ) \
{ \
int i; \
intf_StatMsg( "input buffers stats: pes: %d packets", \
p_buffers->pes.i_depth ); \
STAT_LOOP( FLAGS, NB_LIFO ); \
} \
\
{ \
/* Free PES */ \
pes_packet_t * p_next, * p_packet = p_buffers->pes.p_stack; \
BUFFERS_END_PACKETS_LOOP; \
} \
\
LOOP( FLAGS, NB_LIFO ); \
\
if( p_buffers->i_allocated ) \
{ \
intf_ErrMsg( "input buffers error: %d bytes have not been" \
" freed, expect memory leak", \
p_buffers->i_allocated ); \
} \
\
vlc_mutex_destroy( &p_buffers->lock ); \
free( _p_buffers ); \
} \
}
#define DECLARE_BUFFERS_END( FLAGS, NB_LIFO ) \
BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT, BUFFERS_END_LOOP );
#define DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO ) \
BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT_SHARED, \
BUFFERS_END_LOOP_SHARED );
/*****************************************************************************
* input_NewPacket: return a pointer to a data packet of the appropriate size
*****************************************************************************/
#define BUFFERS_NEWPACKET_EXTRA_DECLARATION( FLAGS, NB_LIFO ) \
_data_packet_t ** pp_data = &p_buf;
#define BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED( FLAGS, NB_LIFO ) \
_data_packet_t * p_data; \
_data_packet_t ** pp_data = &p_data;
#define BUFFERS_NEWPACKET_EXTRA( FLAGS, NB_LIFO )
#define BUFFERS_NEWPACKET_EXTRA_SHARED( FLAGS, NB_LIFO ) \
/* Find a data packet */ \
if( p_buffers->data.p_stack != NULL ) \
{ \
p_data = p_buffers->data.p_stack; \
p_buffers->data.p_stack = p_data->p_next; \
p_buffers->data.i_depth--; \
} \
else \
{ \
p_data = malloc( sizeof( _data_packet_t ) ); \
if( p_data == NULL ) \
{ \
intf_ErrMsg( "Out of memory" ); \
vlc_mutex_unlock( &p_buffers->lock ); \
return( NULL ); \
} \
} \
\
if( i_size == 0 ) \
{ \
/* Warning : in that case, the data packet is left partly \
* uninitialized ; theorically only input_ShareBuffer may call \
* this. */ \
p_data->p_next = NULL; \
p_data->b_discard_payload = 0; \
return( (data_packet_t *)p_data ); \
}
#define BUFFERS_NEWPACKET_END( FLAGS, NB_LIFO, TYPE ) \
(*pp_data)->p_demux_start = (byte_t *)*pp_data + sizeof( TYPE );
#define BUFFERS_NEWPACKET_END_SHARED( FLAGS, NB_LIFO, TYPE ) \
(*pp_data)->_private.p_buffer = p_buf; \
(*pp_data)->p_demux_start = (byte_t *)(*pp_data)->_private.p_buffer \
+ sizeof( TYPE ); \
/* Initialize refcount */ \
p_buf->i_refcount = 1;
#define BUFFERS_NEWPACKET( FLAGS, NB_LIFO, TYPE, NAME, EXTRA_DECLARATION, \
EXTRA, END ) \
/* This one doesn't take p_buffers->lock. */ \
static __inline__ data_packet_t * _input_NewPacket( void * _p_buffers, \
size_t i_size ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
int i_select; \
TYPE * p_buf; \
EXTRA_DECLARATION( FLAGS, NB_LIFO ); \
\
/* Safety check */ \
if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION ) \
{ \
intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)", \
p_buffers->i_allocated ); \
return NULL; \
} \
\
EXTRA( FLAGS, NB_LIFO ); \
\
for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
{ \
if( i_size <= (2 * p_buffers->NAME[i_select].i_average_size \
+ p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
{ \
break; \
} \
} \
\
if( p_buffers->NAME[i_select].p_stack != NULL ) \
{ \
/* Take the packet from the cache */ \
p_buf = p_buffers->NAME[i_select].p_stack; \
p_buffers->NAME[i_select].p_stack = p_buf->p_next; \
p_buffers->NAME[i_select].i_depth--; \
\
/* Reallocate the packet if it is too small or too large */ \
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && \
(p_buf->_private.i_size < i_size \
|| p_buf->_private.i_size > 3 * i_size) ) \
{ \
p_buffers->i_allocated -= p_buf->_private.i_size; \
p_buf = realloc( p_buf, sizeof( TYPE ) + i_size ); \
if( p_buf == NULL ) \
{ \
intf_ErrMsg( "Out of memory" ); \
return NULL; \
} \
p_buf->_private.i_size = i_size; \
p_buffers->i_allocated += i_size; \
} \
} \
else \
{ \
/* Allocate a new packet */ \
p_buf = malloc( sizeof( TYPE ) + i_size ); \
if( p_buf == NULL ) \
{ \
intf_ErrMsg( "Out of memory" ); \
return NULL; \
} \
p_buf->_private.i_size = i_size; \
p_buffers->i_allocated += i_size; \
} \
\
/* Initialize data */ \
END( FLAGS, NB_LIFO, TYPE ); \
(*pp_data)->p_next = NULL; \
(*pp_data)->b_discard_payload = 0; \
(*pp_data)->p_payload_start = (*pp_data)->p_demux_start; \
(*pp_data)->p_payload_end = (*pp_data)->p_payload_start + i_size; \
\
return( (data_packet_t *)*pp_data ); \
} \
\
static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
data_packet_t * p_data; \
\
/* Safety check */ \
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && i_size > INPUT_MAX_PACKET_SIZE ) \
{ \
intf_ErrMsg( "Packet too big (%d)", i_size ); \
return NULL; \
} \
\
vlc_mutex_lock( &p_buffers->lock ); \
p_data = _input_NewPacket( _p_buffers, i_size ); \
vlc_mutex_unlock( &p_buffers->lock ); \
return( p_data ); \
}
#define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ) \
BUFFERS_NEWPACKET( FLAGS, NB_LIFO, _data_packet_t, data, \
BUFFERS_NEWPACKET_EXTRA_DECLARATION, BUFFERS_NEWPACKET_EXTRA, \
BUFFERS_NEWPACKET_END )
#define DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO ) \
BUFFERS_NEWPACKET( FLAGS, NB_LIFO, _data_buffer_t, buffers, \
BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED, \
BUFFERS_NEWPACKET_EXTRA_SHARED, BUFFERS_NEWPACKET_END_SHARED )
/*****************************************************************************
* input_DeletePacket: put a packet back into the cache
*****************************************************************************/
#define BUFFERS_DELETEPACKET_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
_data_packet_t * p_buf = p_data;
#define BUFFERS_DELETEPACKET_EXTRA_SHARED( FLAGS, NB_LIFO, DATA_CACHE_SIZE )\
_data_buffer_t * p_buf = (_data_buffer_t *)p_data->_private.p_buffer; \
\
/* Get rid of the data packet */ \
if( p_buffers->data.i_depth < DATA_CACHE_SIZE ) \
{ \
/* Cache not full : store the packet in it */ \
p_data->p_next = p_buffers->data.p_stack; \
p_buffers->data.p_stack = p_data; \
p_buffers->data.i_depth++; \
} \
else \
{ \
free( p_data ); \
} \
\
/* Decrement refcount */ \
p_buf->i_refcount--; \
if( p_buf->i_refcount > 0 ) \
{ \
return; \
}
#define BUFFERS_DELETEPACKETSTACK_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
_data_packet_t * p_first = (_data_packet_t *)_p_first; \
_data_packet_t ** pp_last = (_data_packet_t **)_pp_last; \
\
/* Small hopeless optimization */ \
if( (FLAGS & BUFFERS_UNIQUE_SIZE) \
&& p_buffers->data[0].i_depth < DATA_CACHE_SIZE ) \
{ \
p_buffers->data[0].i_depth += i_nb; \
*pp_last = p_buffers->data[0].p_stack; \
p_buffers->data[0].p_stack = p_first; \
} \
else /* No semicolon after this or you will die */
#define BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED( FLAGS, NB_LIFO, \
DATA_CACHE_SIZE )
#define BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, TYPE, \
NAME, EXTRA, EXTRA_STACK ) \
/* This one doesn't take p_buffers->lock. */ \
static __inline__ void _input_DeletePacket( void * _p_buffers, \
data_packet_t * _p_data ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
_data_packet_t * p_data = (_data_packet_t *)_p_data; \
int i_select; \
\
while( p_data != NULL ) \
{ \
_data_packet_t * p_next = p_data->p_next; \
\
EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ); \
\
for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
{ \
if( p_buf->_private.i_size <= \
(2 * p_buffers->NAME[i_select].i_average_size \
+ p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
{ \
break; \
} \
} \
\
if( p_buffers->NAME[i_select].i_depth < DATA_CACHE_SIZE ) \
{ \
/* Cache not full : store the packet in it */ \
p_buf->p_next = p_buffers->NAME[i_select].p_stack; \
p_buffers->NAME[i_select].p_stack = p_buf; \
p_buffers->NAME[i_select].i_depth++; \
\
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) ) \
{ \
/* Update Bresenham mean (very approximative) */ \
p_buffers->NAME[i_select].i_average_size = \
( p_buf->_private.i_size \
+ p_buffers->NAME[i_select].i_average_size \
* (INPUT_BRESENHAM_NB - 1) ) \
/ INPUT_BRESENHAM_NB; \
} \
} \
else \
{ \
p_buffers->i_allocated -= p_buf->_private.i_size; \
free( p_buf ); \
} \
\
p_data = p_next; \
} \
} \
\
static void input_DeletePacket( void * _p_buffers, data_packet_t * p_data ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
\
vlc_mutex_lock( &p_buffers->lock ); \
_input_DeletePacket( _p_buffers, p_data ); \
vlc_mutex_unlock( &p_buffers->lock ); \
} \
\
/* Delete a chained list of i_nb data packets. -- needed by DeletePES */ \
static __inline__ void _input_DeletePacketStack( void * _p_buffers, \
data_packet_t * _p_first, \
data_packet_t ** _pp_last, \
unsigned int i_nb ) \
{ \
/* Do not add code before, EXTRA_STACK makes its own declarations. */ \
EXTRA_STACK( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
/* No semicolon - PLEASE */ \
{ \
_input_DeletePacket( _p_buffers, _p_first ); \
} \
}
#define DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_packet_t, \
data, BUFFERS_DELETEPACKET_EXTRA, \
BUFFERS_DELETEPACKETSTACK_EXTRA )
#define DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, \
DATA_CACHE_SIZE ) \
BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_buffer_t, \
buffers, BUFFERS_DELETEPACKET_EXTRA_SHARED, \
BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED )
/*****************************************************************************
* input_DeletePacketStack: optimize deleting of a stack of packets when
* knowing much information
*****************************************************************************/
/* AFAIK, this isn't used by anyone - it is here for completion.
* _input_DeletePacketStack is declared in DeletePacket because it is needed
* by DeletePES. */
#define DECLARE_BUFFERS_DELETEPACKETSTACK( FLAGS, NB_LIFO ) \
static void input_DeletePacketStack( void * _p_buffers, \
data_packet_t * p_first, \
data_packet_t ** pp_last, \
unsigned int i_nb ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
\
vlc_mutex_lock( &p_buffers->lock ); \
_input_DeletePacketStack( _p_buffers, p_first, pp_last, i_nb ); \
vlc_mutex_unlock( &p_buffers->lock ); \
}
/*****************************************************************************
* input_NewPES: return a pointer to a new PES packet
*****************************************************************************/
#define DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ) \
static pes_packet_t * input_NewPES( void * _p_buffers ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
pes_packet_t * p_pes; \
\
vlc_mutex_lock( &p_buffers->lock ); \
\
if( p_buffers->pes.p_stack != NULL ) \
{ \
p_pes = p_buffers->pes.p_stack; \
p_buffers->pes.p_stack = p_pes->p_next; \
p_buffers->pes.i_depth--; \
} \
else \
{ \
p_pes = malloc( sizeof( pes_packet_t ) ); \
if( p_pes == NULL ) \
{ \
intf_ErrMsg( "Out of memory" ); \
vlc_mutex_unlock( &p_buffers->lock ); \
return( NULL ); \
} \
} \
\
vlc_mutex_unlock( &p_buffers->lock ); \
\
/* Initialize data */ \
p_pes->p_next = NULL; \
p_pes->b_data_alignment = p_pes->b_discontinuity = \
p_pes->i_pts = p_pes->i_dts = 0; \
p_pes->i_pes_size = 0; \
p_pes->p_first = p_pes->p_last = NULL; \
p_pes->i_nb_data = 0; \
\
return( p_pes ); \
}
/*****************************************************************************
* input_DeletePES: put a pes and all data packets back into the cache
*****************************************************************************/
#define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, PES_CACHE_SIZE ) \
static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
\
vlc_mutex_lock( &p_buffers->lock ); \
\
while( p_pes != NULL ) \
{ \
pes_packet_t * p_next = p_pes->p_next; \
\
/* Delete all data packets */ \
if( p_pes->p_first != NULL ) \
{ \
_input_DeletePacketStack( _p_buffers, p_pes->p_first, \
&p_pes->p_last->p_next, \
p_pes->i_nb_data ); \
} \
\
if( p_buffers->pes.i_depth < PES_CACHE_SIZE ) \
{ \
/* Cache not full : store the packet in it */ \
p_pes->p_next = p_buffers->pes.p_stack; \
p_buffers->pes.p_stack = p_pes; \
p_buffers->pes.i_depth++; \
} \
else \
{ \
free( p_pes ); \
} \
\
p_pes = p_next; \
} \
\
vlc_mutex_unlock( &p_buffers->lock ); \
}
/*****************************************************************************
* input_BuffersToIO: return an IO vector (only with BUFFERS_UNIQUE_SIZE)
*****************************************************************************/
#define DECLARE_BUFFERS_TOIO( FLAGS, BUFFER_SIZE ) \
static data_packet_t * input_BuffersToIO( void * _p_buffers, \
struct iovec * p_iovec, int i_nb )\
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
data_packet_t * p_data = NULL; \
int i; \
\
vlc_mutex_lock( &p_buffers->lock ); \
\
for( i = i_nb - 1; i >= 0; i-- ) \
{ \
data_packet_t * p_next = _input_NewPacket( _p_buffers, \
BUFFER_SIZE /* UNIQUE_SIZE */ ); \
if( p_next == NULL ) \
{ \
_input_DeletePacket( _p_buffers, p_data ); \
return( NULL ); \
} \
\
p_iovec[i].iov_base = p_next->p_demux_start; \
p_iovec[i].iov_len = BUFFER_SIZE; \
p_next->p_next = p_data; \
p_data = p_next; \
} \
\
vlc_mutex_unlock( &p_buffers->lock ); \
\
return( p_data ); \
}
/*****************************************************************************
* input_ShareBuffer: return a new data_packet to the same buffer
*****************************************************************************/
#define DECLARE_BUFFERS_SHAREBUFFER( FLAGS ) \
static data_packet_t * input_ShareBuffer( void * _p_buffers, \
data_packet_t * _p_shared_data ) \
{ \
_input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
_data_packet_t * p_shared_data = (_data_packet_t *)_p_shared_data; \
_data_packet_t * p_data; \
_data_buffer_t * p_buf = p_shared_data->_private.p_buffer; \
\
vlc_mutex_lock( &p_buffers->lock ); \
\
/* Get new data_packet_t, without a buffer through a special backdoor \
* in _input_NewPacket. */ \
p_data = (_data_packet_t *)_input_NewPacket( _p_buffers, 0 ); \
\
/* Finish initialization of p_data */ \
p_data->_private.p_buffer = p_shared_data->_private.p_buffer; \
p_data->p_demux_start = p_data->p_payload_start \
= (byte_t *)p_shared_data->_private.p_buffer \
+ sizeof( _data_buffer_t ); \
p_data->p_payload_end = p_data->p_demux_start + p_buf->_private.i_size; \
\
/* Update refcount */ \
p_buf->i_refcount++; \
\
vlc_mutex_unlock( &p_buffers->lock ); \
\
return( (data_packet_t *)p_data ); \
}
/* /*
......
...@@ -77,15 +77,6 @@ ...@@ -77,15 +77,6 @@
(p_symbols)->input_DemuxTS = input_DemuxTS; \ (p_symbols)->input_DemuxTS = input_DemuxTS; \
(p_symbols)->input_DemuxPSI = input_DemuxPSI; \ (p_symbols)->input_DemuxPSI = input_DemuxPSI; \
(p_symbols)->input_ClockManageControl = input_ClockManageControl; \ (p_symbols)->input_ClockManageControl = input_ClockManageControl; \
(p_symbols)->input_NetlistInit = input_NetlistInit; \
(p_symbols)->input_NetlistGetiovec = input_NetlistGetiovec; \
(p_symbols)->input_NetlistMviovec = input_NetlistMviovec; \
(p_symbols)->input_NetlistNewPacket = input_NetlistNewPacket; \
(p_symbols)->input_NetlistNewPtr = input_NetlistNewPtr; \
(p_symbols)->input_NetlistNewPES = input_NetlistNewPES; \
(p_symbols)->input_NetlistDeletePacket = input_NetlistDeletePacket; \
(p_symbols)->input_NetlistDeletePES = input_NetlistDeletePES; \
(p_symbols)->input_NetlistEnd = input_NetlistEnd; \
(p_symbols)->aout_CreateFifo = aout_CreateFifo; \ (p_symbols)->aout_CreateFifo = aout_CreateFifo; \
(p_symbols)->aout_DestroyFifo = aout_DestroyFifo; \ (p_symbols)->aout_DestroyFifo = aout_DestroyFifo; \
(p_symbols)->vout_CreateThread = vout_CreateThread; \ (p_symbols)->vout_CreateThread = vout_CreateThread; \
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ac3_adec.c: ac3 decoder module main file * ac3_adec.c: ac3 decoder module main file
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: ac3_adec.c,v 1.5.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: ac3_adec.c,v 1.5.2.2 2001/12/31 01:21:44 massiot Exp $
* *
* Authors: Michel Lespinasse <walken@zoy.org> * Authors: Michel Lespinasse <walken@zoy.org>
* *
...@@ -171,12 +171,12 @@ static int decoder_Run ( decoder_config_t * p_config ) ...@@ -171,12 +171,12 @@ static int decoder_Run ( decoder_config_t * p_config )
sync = 1; sync = 1;
} }
if (DECODER_FIFO_START(*p_ac3thread->p_fifo)->i_pts) if (p_ac3thread->p_fifo->p_first->i_pts)
{ {
p_ac3thread->p_aout_fifo->date[ p_ac3thread->p_aout_fifo->date[
p_ac3thread->p_aout_fifo->l_end_frame] = p_ac3thread->p_aout_fifo->l_end_frame] =
DECODER_FIFO_START(*p_ac3thread->p_fifo)->i_pts; p_ac3thread->p_fifo->p_first->i_pts;
DECODER_FIFO_START(*p_ac3thread->p_fifo)->i_pts = 0; p_ac3thread->p_fifo->p_first->i_pts = 0;
} else { } else {
p_ac3thread->p_aout_fifo->date[ p_ac3thread->p_aout_fifo->date[
p_ac3thread->p_aout_fifo->l_end_frame] = p_ac3thread->p_aout_fifo->l_end_frame] =
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ac3_spdif.c: ac3 pass-through to external decoder with enabled soundcard * ac3_spdif.c: ac3 pass-through to external decoder with enabled soundcard
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: ac3_spdif.c,v 1.5.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: ac3_spdif.c,v 1.5.2.2 2001/12/31 01:21:44 massiot Exp $
* *
* Authors: Stphane Borel <stef@via.ecp.fr> * Authors: Stphane Borel <stef@via.ecp.fr>
* Juha Yrjola <jyrjola@cc.hut.fi> * Juha Yrjola <jyrjola@cc.hut.fi>
...@@ -347,7 +347,7 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream, ...@@ -347,7 +347,7 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream,
p_bit_stream->p_byte += 3; p_bit_stream->p_byte += 3;
p_spdif->i_pts = p_spdif->i_pts =
DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts; p_bit_stream->p_decoder_fifo->p_first->i_pts;
DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts = 0; p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;
} }
} }
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* -dvd_udf to find files * -dvd_udf to find files
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.105.2.1 2001/12/29 23:35:10 sam Exp $ * $Id: input_dvd.c,v 1.105.2.2 2001/12/31 01:21:44 massiot Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -93,10 +93,6 @@ ...@@ -93,10 +93,6 @@
/* how many blocks DVDRead will read in each loop */ /* how many blocks DVDRead will read in each loop */
#define DVD_BLOCK_READ_ONCE 64 #define DVD_BLOCK_READ_ONCE 64
#define DVD_DATA_READ_ONCE (4 * DVD_BLOCK_READ_ONCE)
/* Size of netlist */
#define DVD_NETLIST_SIZE 256
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
...@@ -119,6 +115,21 @@ static int DVDFindCell( thread_dvd_data_t * ); ...@@ -119,6 +115,21 @@ static int DVDFindCell( thread_dvd_data_t * );
static int DVDFindSector( thread_dvd_data_t * ); static int DVDFindSector( thread_dvd_data_t * );
static int DVDChapterSelect( thread_dvd_data_t *, int ); static int DVDChapterSelect( thread_dvd_data_t *, int );
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_UNIQUE_SIZE
#define NB_LIFO 1
DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, 1000 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 1000 );
DECLARE_BUFFERS_TOIO( FLAGS, DVD_LB_SIZE );
DECLARE_BUFFERS_SHAREBUFFER( FLAGS );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much. * we don't pollute the namespace too much.
...@@ -136,10 +147,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -136,10 +147,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_area = DVDSetArea; input.pf_set_area = DVDSetArea;
input.pf_set_program = DVDSetProgram; input.pf_set_program = DVDSetProgram;
input.pf_demux = input_DemuxPS; input.pf_demux = input_DemuxPS;
input.pf_new_packet = input_NetlistNewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NetlistNewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_NetlistDeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_NetlistDeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = DVDRewind; input.pf_rewind = DVDRewind;
input.pf_seek = DVDSeek; input.pf_seek = DVDSeek;
#undef input #undef input
...@@ -194,33 +205,31 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -194,33 +205,31 @@ static void DVDInit( input_thread_t * p_input )
} }
p_input->p_plugin_data = (void *)p_dvd; p_input->p_plugin_data = (void *)p_dvd;
p_input->p_method_data = NULL; if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
p_input->b_error = 1;
return;
}
p_dvd->dvdhandle = (dvdcss_handle) p_input->p_handle; p_dvd->dvdhandle = (dvdcss_handle) p_input->p_handle;
if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 ) if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 )
{ {
intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) ); intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
/* We read DVD_BLOCK_READ_ONCE in each loop, so the input will receive /* We read DVD_BLOCK_READ_ONCE in each loop */
* DVD_DATA_READ_ONCE at most */
p_dvd->i_block_once = DVD_BLOCK_READ_ONCE; p_dvd->i_block_once = DVD_BLOCK_READ_ONCE;
/* this value mustn't be modifed */
p_input->i_read_once = DVD_DATA_READ_ONCE;
/* Reading structures initialisation */
input_NetlistInit( p_input, DVD_NETLIST_SIZE, 2 * DVD_NETLIST_SIZE,
DVD_NETLIST_SIZE, DVD_LB_SIZE, p_dvd->i_block_once );
intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo allocation & initialisation */ /* Ifo allocation & initialisation */
if( IfoCreate( p_dvd ) < 0 ) if( IfoCreate( p_dvd ) < 0 )
{ {
intf_ErrMsg( "dvd error: allcation error in ifo" ); intf_ErrMsg( "dvd error: allcation error in ifo" );
free( p_dvd ); free( p_dvd );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
...@@ -230,6 +239,7 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -230,6 +239,7 @@ static void DVDInit( input_thread_t * p_input )
intf_ErrMsg( "dvd error: fatal failure in ifo" ); intf_ErrMsg( "dvd error: fatal failure in ifo" );
IfoDestroy( p_dvd->p_ifo ); IfoDestroy( p_dvd->p_ifo );
free( p_dvd ); free( p_dvd );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
...@@ -289,9 +299,8 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -289,9 +299,8 @@ static void DVDInit( input_thread_t * p_input )
i_chapter = 1; i_chapter = 1;
} }
p_input->stream.pp_areas[i_title]->i_part = i_chapter;
p_area = p_input->stream.pp_areas[i_title]; p_area = p_input->stream.pp_areas[i_title];
p_area->i_part = i_chapter;
/* set title, chapter, audio and subpic */ /* set title, chapter, audio and subpic */
DVDSetArea( p_input, p_area ); DVDSetArea( p_input, p_area );
...@@ -322,7 +331,7 @@ static void DVDOpen( struct input_thread_s *p_input ) ...@@ -322,7 +331,7 @@ static void DVDOpen( struct input_thread_s *p_input )
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
/* Parse input string : dvd:device[:rawdevice] */ /* Parse input string : dvd:device[@rawdevice] */
if( strlen( p_input->p_source ) > 4 if( strlen( p_input->p_source ) > 4
&& !strncasecmp( p_input->p_source, "dvd:", 4 ) ) && !strncasecmp( p_input->p_source, "dvd:", 4 ) )
{ {
...@@ -383,7 +392,7 @@ static void DVDEnd( input_thread_t * p_input ) ...@@ -383,7 +392,7 @@ static void DVDEnd( input_thread_t * p_input )
free( p_dvd ); free( p_dvd );
input_NetlistEnd( p_input ); input_BuffersEnd( p_input->p_method_data );
} }
/***************************************************************************** /*****************************************************************************
...@@ -816,20 +825,17 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -816,20 +825,17 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
return 0; return 0;
} }
/***************************************************************************** /*****************************************************************************
* DVDRead: reads data packets into the netlist. * DVDRead: reads data packets.
***************************************************************************** *****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* EOF. * packets.
*****************************************************************************/ *****************************************************************************/
static int DVDRead( input_thread_t * p_input, static int DVDRead( input_thread_t * p_input,
data_packet_t ** pp_packets ) data_packet_t ** pp_data )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
netlist_t * p_netlist; struct iovec p_vec[DVD_BLOCK_READ_ONCE];
struct iovec * p_vec;
struct data_packet_s * pp_data[DVD_DATA_READ_ONCE];
u8 * pi_cur; u8 * pi_cur;
int i_block_once; int i_block_once;
int i_packet_size; int i_packet_size;
...@@ -838,12 +844,12 @@ static int DVDRead( input_thread_t * p_input, ...@@ -838,12 +844,12 @@ static int DVDRead( input_thread_t * p_input,
int i_pos; int i_pos;
int i_read_blocks; int i_read_blocks;
int i_sector; int i_sector;
boolean_t b_eof;
boolean_t b_eot;
boolean_t b_eoc; boolean_t b_eoc;
data_packet_t * p_data;
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = (netlist_t *)p_input->p_method_data;
*pp_data = NULL;
b_eoc = 0; b_eoc = 0;
i_sector = p_dvd->i_title_start + p_dvd->i_sector; i_sector = p_dvd->i_title_start + p_dvd->i_sector;
...@@ -861,7 +867,6 @@ static int DVDRead( input_thread_t * p_input, ...@@ -861,7 +867,6 @@ static int DVDRead( input_thread_t * p_input,
/* Find cell index in adress map */ /* Find cell index in adress map */
if( DVDFindSector( p_dvd ) < 0 ) if( DVDFindSector( p_dvd ) < 0 )
{ {
pp_packets[0] = NULL;
intf_ErrMsg( "dvd error: can't find next cell" ); intf_ErrMsg( "dvd error: can't find next cell" );
return 1; return 1;
} }
...@@ -907,23 +912,20 @@ static int DVDRead( input_thread_t * p_input, ...@@ -907,23 +912,20 @@ static int DVDRead( input_thread_t * p_input,
/* /*
intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter ); intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter );
*/ */
p_netlist->i_read_once = i_block_once;
/* Get an iovec pointer */ /* Get iovecs */
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL ) *pp_data = p_data = input_BuffersToIO( p_input->p_method_data, p_vec,
DVD_BLOCK_READ_ONCE );
if ( p_data == NULL )
{ {
intf_ErrMsg( "dvd error: can't get iovec" ); return( -1 );
return -1;
} }
/* Reads from DVD */ /* Reads from DVD */
i_read_blocks = dvdcss_readv( p_dvd->dvdhandle, p_vec, i_read_blocks = dvdcss_readv( p_dvd->dvdhandle, p_vec,
i_block_once, DVDCSS_READ_DECRYPT ); i_block_once, DVDCSS_READ_DECRYPT );
/* Update netlist indexes: we don't do it in DVDGetiovec since we
* need know the real number of blocks read */
input_NetlistMviovec( p_netlist, i_read_blocks, pp_data );
/* Update global position */ /* Update global position */
p_dvd->i_sector += i_read_blocks; p_dvd->i_sector += i_read_blocks;
...@@ -932,42 +934,50 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o ...@@ -932,42 +934,50 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o
/* Read headers to compute payload length */ /* Read headers to compute payload length */
for( i_iovec = 0 ; i_iovec < i_read_blocks ; i_iovec++ ) for( i_iovec = 0 ; i_iovec < i_read_blocks ; i_iovec++ )
{ {
data_packet_t * p_current = p_data;
i_pos = 0; i_pos = 0;
while( i_pos < p_netlist->i_buffer_size ) while( i_pos < DVD_LB_SIZE )
{ {
pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos; pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos;
/*default header */ /* Default header */
if( U32_AT( pi_cur ) != 0x1BA ) if( U32_AT( pi_cur ) != 0x1BA )
{ {
/* That's the case for all packets, except pack header. */ /* That's the case for all packets, except pack header. */
i_packet_size = U16_AT( pi_cur + 4 ); i_packet_size = U16_AT( pi_cur + 4 );
pp_packets[i_packet] = input_NetlistNewPtr( p_netlist );
(*pp_data[i_iovec]->pi_refcount)++;
pp_packets[i_packet]->pi_refcount =
pp_data[i_iovec]->pi_refcount;
pp_packets[i_packet]->p_buffer = pp_data[i_iovec]->p_buffer;
} }
else else
{ {
/* MPEG-2 Pack header. */ /* MPEG-2 Pack header. */
i_packet_size = 8; i_packet_size = 8;
pp_packets[i_packet] = pp_data[i_iovec];
} }
pp_packets[i_packet]->p_payload_start = if( i_pos != 0 )
pp_packets[i_packet]->p_buffer + i_pos; {
*pp_data = input_ShareBuffer( p_input->p_method_data,
p_current );
}
else
{
*pp_data = p_data;
p_data = p_data->p_next;
}
(*pp_data)->p_payload_start = (*pp_data)->p_demux_start =
(*pp_data)->p_demux_start + i_pos;
pp_packets[i_packet]->p_payload_end = (*pp_data)->p_payload_end =
pp_packets[i_packet]->p_payload_start + i_packet_size + 6; (*pp_data)->p_payload_start + i_packet_size + 6;
i_packet++; i_packet++;
i_pos += i_packet_size + 6; i_pos += i_packet_size + 6;
pp_data = &(*pp_data)->p_next;
} }
} }
pp_packets[i_packet] = NULL; p_input->pf_delete_packet( p_input->p_method_data, p_data );
*pp_data = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -981,33 +991,32 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o ...@@ -981,33 +991,32 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
} }
b_eot = !( p_input->stream.p_selected_area->i_tell if( p_input->stream.p_selected_area->i_tell
< p_input->stream.p_selected_area->i_size ); >= p_input->stream.p_selected_area->i_size )
b_eof = b_eot && ( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb );
if( b_eof )
{ {
vlc_mutex_unlock( &p_input->stream.stream_lock ); if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb )
return 1; {
} /* EOF */
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0;
}
if( b_eot ) /* EOT */
{
intf_WarnMsg( 4, "dvd info: new title" ); intf_WarnMsg( 4, "dvd info: new title" );
p_dvd->i_title++; p_dvd->i_title++;
DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] ); DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] );
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0; return( i_packet );
} }
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
if( i_read_blocks == i_block_once ) if( i_read_blocks != i_block_once )
{ {
return 0; return -1;
} }
return -1; return( i_packet );
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* It depends on: libdvdread for ifo files and block reading. * It depends on: libdvdread for ifo files and block reading.
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: input_dvdread.c,v 1.3 2001/12/07 18:33:07 sam Exp $ * $Id: input_dvdread.c,v 1.3.2.1 2001/12/31 01:21:44 massiot Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -85,10 +85,6 @@ ...@@ -85,10 +85,6 @@
/* how many blocks DVDRead will read in each loop */ /* how many blocks DVDRead will read in each loop */
#define DVD_BLOCK_READ_ONCE 64 #define DVD_BLOCK_READ_ONCE 64
#define DVD_DATA_READ_ONCE (4 * DVD_BLOCK_READ_ONCE)
/* Size of netlist */
#define DVD_NETLIST_SIZE 512
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
...@@ -100,6 +96,7 @@ static void DvdReadEnd ( struct input_thread_s * ); ...@@ -100,6 +96,7 @@ static void DvdReadEnd ( struct input_thread_s * );
static void DvdReadOpen ( struct input_thread_s * ); static void DvdReadOpen ( struct input_thread_s * );
static void DvdReadClose ( struct input_thread_s * ); static void DvdReadClose ( struct input_thread_s * );
static int DvdReadSetArea ( struct input_thread_s *, struct input_area_s * ); static int DvdReadSetArea ( struct input_thread_s *, struct input_area_s * );
static int DvdReadSetProgram( struct input_thread_s *, pgrm_descriptor_t * );
static int DvdReadRead ( struct input_thread_s *, data_packet_t ** ); static int DvdReadRead ( struct input_thread_s *, data_packet_t ** );
static void DvdReadSeek ( struct input_thread_s *, off_t ); static void DvdReadSeek ( struct input_thread_s *, off_t );
static int DvdReadRewind ( struct input_thread_s * ); static int DvdReadRewind ( struct input_thread_s * );
...@@ -108,6 +105,21 @@ static int DvdReadRewind ( struct input_thread_s * ); ...@@ -108,6 +105,21 @@ static int DvdReadRewind ( struct input_thread_s * );
static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data ); static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data );
static void DvdReadFindCell ( thread_dvd_data_t * p_dvd ); static void DvdReadFindCell ( thread_dvd_data_t * p_dvd );
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_UNIQUE_SIZE
#define NB_LIFO 1
DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, 1000 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 1000 );
DECLARE_BUFFERS_TOIO( FLAGS, DVD_VIDEO_LB_LEN );
DECLARE_BUFFERS_SHAREBUFFER( FLAGS );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much. * we don't pollute the namespace too much.
...@@ -123,11 +135,12 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -123,11 +135,12 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_init_bit_stream = InitBitstream; input.pf_init_bit_stream = InitBitstream;
input.pf_read = DvdReadRead; input.pf_read = DvdReadRead;
input.pf_set_area = DvdReadSetArea; input.pf_set_area = DvdReadSetArea;
input.pf_set_program = DvdReadSetProgram;
input.pf_demux = input_DemuxPS; input.pf_demux = input_DemuxPS;
input.pf_new_packet = input_NetlistNewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NetlistNewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_NetlistDeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_NetlistDeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = DvdReadRewind; input.pf_rewind = DvdReadRewind;
input.pf_seek = DvdReadSeek; input.pf_seek = DvdReadSeek;
#undef input #undef input
...@@ -157,7 +170,7 @@ static int DvdReadProbe( probedata_t *p_data ) ...@@ -157,7 +170,7 @@ static int DvdReadProbe( probedata_t *p_data )
/* If the user specified "dvdread:" then he probably wants /* If the user specified "dvdread:" then he probably wants
* to use libdvdread */ * to use libdvdread */
i_score = 100; i_score = 100;
psz_name += 4; psz_name += 8;
} }
return( i_score ); return( i_score );
...@@ -188,24 +201,22 @@ static void DvdReadInit( input_thread_t * p_input ) ...@@ -188,24 +201,22 @@ static void DvdReadInit( input_thread_t * p_input )
p_dvd->p_vts_file = NULL; p_dvd->p_vts_file = NULL;
p_input->p_plugin_data = (void *)p_dvd; p_input->p_plugin_data = (void *)p_dvd;
p_input->p_method_data = NULL;
/* We read DVD_BLOCK_READ_ONCE in each loop, so the input will receive if( (p_input->p_method_data = input_BuffersInit()) == NULL )
* DVD_DATA_READ_ONCE at most */ {
p_dvd->i_block_once = DVD_BLOCK_READ_ONCE; free( p_dvd );
/* this value mustn't be modifed */ p_input->b_error = 1;
p_input->i_read_once = DVD_DATA_READ_ONCE; return;
}
/* Reading structures initialisation */ /* We read DVD_BLOCK_READ_ONCE in each loop */
input_NetlistInit( p_input, DVD_NETLIST_SIZE, 2 * DVD_NETLIST_SIZE, p_dvd->i_block_once = DVD_BLOCK_READ_ONCE;
DVD_NETLIST_SIZE, DVD_VIDEO_LB_LEN, p_dvd->i_block_once );
intf_WarnMsg( 2, "dvdread info: netlist initialized" );
/* Ifo allocation & initialisation */ /* Ifo allocation & initialisation */
if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) ) if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) )
{ {
intf_ErrMsg( "dvdread error: can't open VMG info" ); intf_ErrMsg( "dvdread error: can't open VMG info" );
DVDClose( p_dvd->p_dvdread ); input_BuffersEnd( p_input->p_method_data );
free( p_dvd ); free( p_dvd );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
...@@ -349,9 +360,16 @@ static void DvdReadEnd( input_thread_t * p_input ) ...@@ -349,9 +360,16 @@ static void DvdReadEnd( input_thread_t * p_input )
ifoClose( p_dvd->p_vts_file ); ifoClose( p_dvd->p_vts_file );
ifoClose( p_dvd->p_vmg_file ); ifoClose( p_dvd->p_vmg_file );
/* Close netlist */ input_BuffersEnd( p_input->p_method_data );
input_NetlistEnd( p_input ); }
p_input->p_method_data = NULL;
/*****************************************************************************
* DvdReadSetProgram: Does nothing, a DVD is mono-program
*****************************************************************************/
static int DvdReadSetProgram( input_thread_t * p_input,
pgrm_descriptor_t * p_program )
{
return 0;
} }
#define p_pgc p_dvd->p_cur_pgc #define p_pgc p_dvd->p_cur_pgc
...@@ -511,23 +529,24 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -511,23 +529,24 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
} }
free( p_input->stream.pp_selected_es ); free( p_input->stream.pp_selected_es );
input_DelProgram( p_input, p_input->stream.pp_programs[0] ); input_DelProgram( p_input, p_input->stream.p_selected_program );
p_input->stream.pp_selected_es = NULL; p_input->stream.pp_selected_es = NULL;
p_input->stream.i_selected_es_number = 0; p_input->stream.i_selected_es_number = 0;
} }
input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) ); input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
/* No PSM to read in DVD mode, we already have all information */ /* No PSM to read in DVD mode, we already have all information */
p_input->stream.pp_programs[0]->b_is_ok = 1; p_input->stream.p_selected_program->b_is_ok = 1;
p_es = NULL; p_es = NULL;
/* ES 0 -> video MPEG2 */ /* ES 0 -> video MPEG2 */
// IfoPrintVideo( p_dvd ); // IfoPrintVideo( p_dvd );
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], 0xe0, 0 ); p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xe0, 0 );
p_es->i_stream_id = 0xe0; p_es->i_stream_id = 0xe0;
p_es->i_type = MPEG2_VIDEO_ES; p_es->i_type = MPEG2_VIDEO_ES;
p_es->i_cat = VIDEO_ES; p_es->i_cat = VIDEO_ES;
...@@ -558,7 +577,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -558,7 +577,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
case 0x00: /* AC3 */ case 0x00: /* AC3 */
i_id = ( ( 0x80 + i_position ) << 8 ) | 0xbd; i_id = ( ( 0x80 + i_position ) << 8 ) | 0xbd;
p_es = input_AddES( p_input, p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 ); p_input->stream.p_selected_program, i_id, 0 );
p_es->i_stream_id = 0xbd; p_es->i_stream_id = 0xbd;
p_es->i_type = AC3_AUDIO_ES; p_es->i_type = AC3_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
...@@ -572,7 +591,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -572,7 +591,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
case 0x03: /* MPEG audio */ case 0x03: /* MPEG audio */
i_id = 0xc0 + i_position; i_id = 0xc0 + i_position;
p_es = input_AddES( p_input, p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 ); p_input->stream.p_selected_program, i_id, 0 );
p_es->i_stream_id = i_id; p_es->i_stream_id = i_id;
p_es->i_type = MPEG2_AUDIO_ES; p_es->i_type = MPEG2_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
...@@ -586,7 +605,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -586,7 +605,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
i_id = ( ( 0xa0 + i_position ) << 8 ) | 0xbd; i_id = ( ( 0xa0 + i_position ) << 8 ) | 0xbd;
p_es = input_AddES( p_input, p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 ); p_input->stream.p_selected_program, i_id, 0 );
p_es->i_stream_id = i_id; p_es->i_stream_id = i_id;
p_es->i_type = LPCM_AUDIO_ES; p_es->i_type = LPCM_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
...@@ -651,7 +670,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -651,7 +670,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
i_id = ( ( 0x20 + i_position ) << 8 ) | 0xbd; i_id = ( ( 0x20 + i_position ) << 8 ) | 0xbd;
p_es = input_AddES( p_input, p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 ); p_input->stream.p_selected_program, i_id, 0 );
p_es->i_stream_id = 0xbd; p_es->i_stream_id = 0xbd;
p_es->i_type = DVD_SPU_ES; p_es->i_type = DVD_SPU_ES;
p_es->i_cat = SPU_ES; p_es->i_cat = SPU_ES;
...@@ -772,13 +791,11 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -772,13 +791,11 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
* EOF. * EOF.
*****************************************************************************/ *****************************************************************************/
static int DvdReadRead( input_thread_t * p_input, static int DvdReadRead( input_thread_t * p_input,
data_packet_t ** pp_packets ) data_packet_t ** pp_data )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
netlist_t * p_netlist;
u8 p_data[DVD_VIDEO_LB_LEN]; u8 p_data[DVD_VIDEO_LB_LEN];
struct iovec * p_vec; struct iovec p_vec[DVD_BLOCK_READ_ONCE];
struct data_packet_s * pp_data[DVD_DATA_READ_ONCE];
u8 * pi_cur; u8 * pi_cur;
int i_blocks; int i_blocks;
int i_read; int i_read;
...@@ -786,9 +803,12 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -786,9 +803,12 @@ static int DvdReadRead( input_thread_t * p_input,
int i_packet_size; int i_packet_size;
int i_packet; int i_packet;
int i_pos; int i_pos;
data_packet_t * p_data_p;
boolean_t b_eot = 0;
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = (netlist_t *)p_input->p_method_data;
*pp_data = NULL;
/* /*
* Playback by cell in this pgc, starting at the cell for our chapter. * Playback by cell in this pgc, starting at the cell for our chapter.
...@@ -810,26 +830,35 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -810,26 +830,35 @@ static int DvdReadRead( input_thread_t * p_input,
return -1; return -1;
} }
/* basic check to be sure we don't have a empty title
* go to next title if so */
assert( p_data[41] == 0xbf && p_data[1027] == 0xbf ); assert( p_data[41] == 0xbf && p_data[1027] == 0xbf );
if( p_data[41] == 0xbf && p_data[1027] == 0xbf )
{
/*
* Parse the contained dsi packet.
*/
/* DvdReadHandleDSI( p_dvd, p_data );
* Parse the contained dsi packet.
*/
DvdReadHandleDSI( p_dvd, p_data ); /* End of File */
if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 )
{
return 1;
}
/* End of File */ assert( p_dvd->i_pack_len < 1024 );
if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 ) /* FIXME: Ugly kludge: we send the pack block to the input for it
* sometimes has a zero scr and restart the sync */
//p_dvd->i_cur_block ++;
p_dvd->i_pack_len++;
}
else
{ {
return 1; b_eot = 1;
p_dvd->i_pack_len = 0;
return 1;
} }
assert( p_dvd->i_pack_len < 1024 );
/* Ugly kludge: we send the pack block to the input for it
* sometimes has a zero scr and restart the sync */
// p_dvd->i_cur_block ++;
p_dvd->i_pack_len++;
} }
/* /*
...@@ -838,13 +867,14 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -838,13 +867,14 @@ static int DvdReadRead( input_thread_t * p_input,
i_blocks = p_dvd->i_pack_len >= DVD_BLOCK_READ_ONCE i_blocks = p_dvd->i_pack_len >= DVD_BLOCK_READ_ONCE
? DVD_BLOCK_READ_ONCE : p_dvd->i_pack_len; ? DVD_BLOCK_READ_ONCE : p_dvd->i_pack_len;
p_dvd->i_pack_len -= i_blocks; p_dvd->i_pack_len -= i_blocks;
p_netlist->i_read_once = i_blocks;
/* Get an iovec pointer */ /* Get iovecs */
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL ) *pp_data = p_data_p = input_BuffersToIO( p_input->p_method_data, p_vec,
DVD_BLOCK_READ_ONCE );
if ( p_data_p == NULL )
{ {
intf_ErrMsg( "dvdread error: can't get iovec" ); return( -1 );
return -1;
} }
/* Reads from DVD */ /* Reads from DVD */
...@@ -861,18 +891,15 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -861,18 +891,15 @@ static int DvdReadRead( input_thread_t * p_input,
/* /*
intf_WarnMsg( 12, "dvdread i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block ); intf_WarnMsg( 12, "dvdread i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block );
*/ */
/* Update netlist indexes: we don't do it in DVDGetiovec since we
* need know the real number of blocks read */
input_NetlistMviovec( p_netlist, i_read, pp_data );
i_packet = 0; i_packet = 0;
/* Read headers to compute payload length */ /* Read headers to compute payload length */
for( i_iovec = 0 ; i_iovec < i_read ; i_iovec++ ) for( i_iovec = 0 ; i_iovec < i_read ; i_iovec++ )
{ {
data_packet_t * p_current = p_data_p;
i_pos = 0; i_pos = 0;
while( i_pos < p_netlist->i_buffer_size ) while( i_pos < DVD_VIDEO_LB_LEN )
{ {
pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos; pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos;
...@@ -881,35 +908,48 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -881,35 +908,48 @@ static int DvdReadRead( input_thread_t * p_input,
{ {
/* That's the case for all packets, except pack header. */ /* That's the case for all packets, except pack header. */
i_packet_size = U16_AT( pi_cur + 4 ); i_packet_size = U16_AT( pi_cur + 4 );
pp_packets[i_packet] = input_NetlistNewPtr( p_netlist );
(*pp_data[i_iovec]->pi_refcount)++;
pp_packets[i_packet]->pi_refcount =
pp_data[i_iovec]->pi_refcount;
pp_packets[i_packet]->p_buffer = pp_data[i_iovec]->p_buffer;
} }
else else
{ {
/* MPEG-2 Pack header. */ /* MPEG-2 Pack header. */
i_packet_size = 8; i_packet_size = 8;
pp_packets[i_packet] = pp_data[i_iovec]; }
if( i_pos != 0 )
{
*pp_data = input_ShareBuffer( p_input->p_method_data,
p_current );
}
else
{
*pp_data = p_data_p;
p_data_p = p_data_p->p_next;
} }
pp_packets[i_packet]->p_payload_start = (*pp_data)->p_payload_start = (*pp_data)->p_demux_start =
pp_packets[i_packet]->p_buffer + i_pos; (*pp_data)->p_demux_start + i_pos;
pp_packets[i_packet]->p_payload_end = (*pp_data)->p_payload_end =
pp_packets[i_packet]->p_payload_start + i_packet_size + 6; (*pp_data)->p_payload_start + i_packet_size + 6;
pp_packets[i_packet]->p_next = NULL; // pp_packets[i_packet]->p_next = NULL;
pp_packets[i_packet]->b_discard_payload = 0; // pp_packets[i_packet]->b_discard_payload = 0;
i_packet++; i_packet++;
i_pos += i_packet_size + 6; i_pos += i_packet_size + 6;
pp_data = &(*pp_data)->p_next;
} }
} }
pp_packets[i_packet] = NULL; p_input->pf_delete_packet( p_input->p_method_data, p_data_p );
*pp_data = NULL;
while( p_data_p != NULL )
{
data_packet_t * p_next = p_data_p->p_next;
p_input->pf_delete_packet( p_input->p_method_data, p_data_p );
p_data_p = p_next;
}
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -924,7 +964,25 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -924,7 +964,25 @@ static int DvdReadRead( input_thread_t * p_input,
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
p_dvd->b_eoc = 0; p_dvd->b_eoc = 0;
} }
if( p_input->stream.p_selected_area->i_tell
>= p_input->stream.p_selected_area->i_size || b_eot )
{
if( ( p_input->stream.p_selected_area->i_id + 1 ) >=
p_input->stream.i_area_nb )
{
/* EOF */
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 1;
}
/* EOT */
intf_WarnMsg( 4, "dvd info: new title" );
DvdReadSetArea( p_input, p_input->stream.pp_areas[
p_input->stream.p_selected_area->i_id+1] );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0;
}
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* lpcm_decoder_thread.c: lpcm decoder thread * lpcm_decoder_thread.c: lpcm decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: lpcm_adec.c,v 1.3.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: lpcm_adec.c,v 1.3.2.2 2001/12/31 01:21:44 massiot Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@videolan.org> * Henri Fallon <henri@videolan.org>
...@@ -187,11 +187,11 @@ void DecodeFrame( lpcmdec_thread_t * p_lpcmdec ) ...@@ -187,11 +187,11 @@ void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
int i_loop; int i_loop;
byte_t byte1, byte2; byte_t byte1, byte2;
if( DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts ) if( p_lpcmdec->p_fifo->p_first->i_pts )
{ {
p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts; p_lpcmdec->p_fifo->p_first->i_pts;
DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0; p_lpcmdec->p_fifo->p_first->i_pts = 0;
} }
else else
{ {
......
...@@ -62,9 +62,9 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream) ...@@ -62,9 +62,9 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
byte_t buffer[ADEC_FRAME_SIZE]; byte_t buffer[ADEC_FRAME_SIZE];
/* Store time stamp of current frame */ /* Store time stamp of current frame */
if ( DECODER_FIFO_START(*p_mad_adec->p_fifo)->i_pts ) { if ( p_mad_adec->p_fifo->p_first->i_pts ) {
p_mad_adec->i_pts_save = DECODER_FIFO_START(*p_mad_adec->p_fifo)->i_pts; p_mad_adec->i_pts_save = p_mad_adec->p_fifo->p_first->i_pts;
DECODER_FIFO_START(*p_mad_adec->p_fifo)->i_pts = 0; p_mad_adec->p_fifo->p_first->i_pts = 0;
} }
else { else {
p_mad_adec->i_pts_save = LAST_MDATE; p_mad_adec->i_pts_save = LAST_MDATE;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_es.c: Elementary Stream demux and packet management * input_es.c: Elementary Stream demux and packet management
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: input_es.c,v 1.16.2.1 2001/12/10 15:56:57 massiot Exp $ * $Id: input_es.c,v 1.16.2.2 2001/12/31 01:21:45 massiot Exp $
* *
* Author: Christophe Massiot <massiot@via.ecp.fr> * Author: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
*****************************************************************************/ *****************************************************************************/
static int ESProbe ( probedata_t * ); static int ESProbe ( probedata_t * );
static int ESRead ( struct input_thread_s *, static int ESRead ( struct input_thread_s *,
data_packet_t * p_packets[INPUT_READ_ONCE] ); data_packet_t ** );
static void ESInit ( struct input_thread_s * ); static void ESInit ( struct input_thread_s * );
static void ESEnd ( struct input_thread_s * ); static void ESEnd ( struct input_thread_s * );
static void ESSeek ( struct input_thread_s *, off_t ); static void ESSeek ( struct input_thread_s *, off_t );
...@@ -89,6 +89,20 @@ static void ESInitBitstream( struct bit_stream_s *, struct decoder_fifo_s *, ...@@ -89,6 +89,20 @@ static void ESInitBitstream( struct bit_stream_s *, struct decoder_fifo_s *,
void * ); void * );
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_UNIQUE_SIZE
#define NB_LIFO 1
DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_TOIO( FLAGS, ES_PACKET_SIZE );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much. * we don't pollute the namespace too much.
...@@ -106,10 +120,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -106,10 +120,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_program = ESSetProgram; input.pf_set_program = ESSetProgram;
input.pf_read = ESRead; input.pf_read = ESRead;
input.pf_demux = ESDemux; input.pf_demux = ESDemux;
input.pf_new_packet = input_NetlistNewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NetlistNewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_NetlistDeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_NetlistDeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = NULL; input.pf_rewind = NULL;
input.pf_seek = ESSeek; input.pf_seek = ESSeek;
#undef input #undef input
...@@ -141,27 +155,24 @@ static void ESInit( input_thread_t * p_input ) ...@@ -141,27 +155,24 @@ static void ESInit( input_thread_t * p_input )
{ {
es_descriptor_t * p_es; es_descriptor_t * p_es;
p_input->p_method_data = NULL; if( (p_input->p_method_data = input_BuffersInit()) == NULL )
/* Initialize netlist */
if( input_NetlistInit( p_input, NB_DATA, NB_DATA, NB_PES, ES_PACKET_SIZE,
INPUT_READ_ONCE ) )
{ {
intf_ErrMsg( "ES input : Could not initialize netlist" ); p_input->b_error = 1;
return; return;
} }
/* FIXME : detect if InitStream failed */ /* FIXME : detect if InitStream failed */
input_InitStream( p_input, 0 ); input_InitStream( p_input, 0 );
input_AddProgram( p_input, 0, 0 ); input_AddProgram( p_input, 0, 0 );
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], 0xE0, 0 ); p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xE0, 0 );
p_es->i_stream_id = 0xE0; p_es->i_stream_id = 0xE0;
p_es->i_type = MPEG1_VIDEO_ES; p_es->i_type = MPEG1_VIDEO_ES;
p_es->i_cat = VIDEO_ES; p_es->i_cat = VIDEO_ES;
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
p_input->stream.p_selected_area->i_tell = 0; p_input->stream.p_selected_area->i_tell = 0;
p_input->stream.pp_programs[0]->b_is_ok = 1; p_input->stream.p_selected_program->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
} }
...@@ -170,49 +181,57 @@ static void ESInit( input_thread_t * p_input ) ...@@ -170,49 +181,57 @@ static void ESInit( input_thread_t * p_input )
*****************************************************************************/ *****************************************************************************/
static void ESEnd( input_thread_t * p_input ) static void ESEnd( input_thread_t * p_input )
{ {
input_BuffersEnd( p_input->p_method_data );
} }
/***************************************************************************** /*****************************************************************************
* ESRead: reads data packets * ESRead: reads data packets
***************************************************************************** *****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* EOF. * packets.
*****************************************************************************/ *****************************************************************************/
static int ESRead( input_thread_t * p_input, static int ESRead( input_thread_t * p_input,
data_packet_t * pp_packets[INPUT_READ_ONCE] ) data_packet_t ** pp_data )
{ {
int i_read; int i_read;
struct iovec * p_iovec; struct iovec p_iovec[ES_READ_ONCE];
data_packet_t * p_data;
/* Get iovecs */ /* Get iovecs */
p_iovec = input_NetlistGetiovec( p_input->p_method_data ); *pp_data = p_data = input_BuffersToIO( p_input->p_method_data, p_iovec,
ES_READ_ONCE );
if ( p_iovec == NULL ) if ( p_data == NULL )
{ {
return( -1 ); /* empty netlist */ return( -1 );
} }
memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) ); i_read = readv( p_input->i_handle, p_iovec, ES_READ_ONCE );
i_read = readv( p_input->i_handle, p_iovec, INPUT_READ_ONCE );
if( i_read == -1 ) if( i_read == -1 )
{ {
intf_ErrMsg( "input error: ES readv error" ); intf_ErrMsg( "input error: ES readv error" );
p_input->pf_delete_packet( p_input->p_method_data, p_data );
return( -1 ); return( -1 );
} }
p_input->stream.p_selected_area->i_tell += i_read;
i_read /= ES_PACKET_SIZE;
/* EOF */ if( i_read != ES_READ_ONCE )
if( i_read == 0 && p_input->stream.b_seekable )
{ {
return( 1 ); /* We got fewer packets than wanted. Give remaining packets
} * back to the buffer allocator. */
int i_loop;
input_NetlistMviovec( p_input->p_method_data, for( i_loop = 0; i_loop < i_read; i_loop++ )
(int)(i_read/ES_PACKET_SIZE), pp_packets ); {
pp_data = &(*pp_data)->p_next;
}
p_input->stream.p_selected_area->i_tell += i_read; p_input->pf_delete_packet( p_input->p_method_data, *pp_data );
*pp_data = NULL;
}
return( 0 ); return( i_read );
} }
/***************************************************************************** /*****************************************************************************
...@@ -241,7 +260,7 @@ static void ESDemux( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -241,7 +260,7 @@ static void ESDemux( input_thread_t * p_input, data_packet_t * p_data )
{ {
pes_packet_t * p_pes = p_input->pf_new_pes( p_input->p_method_data ); pes_packet_t * p_pes = p_input->pf_new_pes( p_input->p_method_data );
decoder_fifo_t * p_fifo = decoder_fifo_t * p_fifo =
p_input->stream.pp_programs[0]->pp_es[0]->p_decoder_fifo; p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
if( p_pes == NULL ) if( p_pes == NULL )
{ {
...@@ -251,22 +270,23 @@ static void ESDemux( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -251,22 +270,23 @@ static void ESDemux( input_thread_t * p_input, data_packet_t * p_data )
} }
p_pes->i_rate = p_input->stream.control.i_rate; p_pes->i_rate = p_input->stream.control.i_rate;
p_pes->p_first = p_data; p_pes->p_first = p_pes->p_last = p_data;
p_pes->i_nb_data = 1;
if( (p_input->stream.pp_programs[0]->i_synchro_state == SYNCHRO_REINIT) if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
| (input_ClockManageControl( p_input, p_input->stream.pp_programs[0], | (input_ClockManageControl( p_input,
(mtime_t)0 ) == PAUSE_S) ) p_input->stream.p_selected_program,
(mtime_t)0 ) == PAUSE_S) )
{ {
intf_WarnMsg( 2, "synchro reinit" ); intf_WarnMsg( 2, "synchro reinit" );
p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY; p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
p_input->stream.pp_programs[0]->i_synchro_state = SYNCHRO_OK; p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
} }
input_DecodePES( p_fifo, p_pes ); input_DecodePES( p_fifo, p_pes );
vlc_mutex_lock( &p_fifo->data_lock ); vlc_mutex_lock( &p_fifo->data_lock );
if( ( (DECODER_FIFO_END( *p_fifo ) - DECODER_FIFO_START( *p_fifo )) if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
& FIFO_SIZE ) >= MAX_PACKETS_IN_FIFO )
{ {
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock ); vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
} }
...@@ -290,18 +310,23 @@ static void ESNextDataPacket( bit_stream_t * p_bit_stream ) ...@@ -290,18 +310,23 @@ static void ESNextDataPacket( bit_stream_t * p_bit_stream )
* time to jump to the next PES packet */ * time to jump to the next PES packet */
if( p_bit_stream->p_data->p_next == NULL ) if( p_bit_stream->p_data->p_next == NULL )
{ {
/* We are going to read/write the start and end indexes of the pes_packet_t * p_next;
* 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 ); vlc_mutex_lock( &p_fifo->data_lock );
/* Free the previous PES packet. */ /* Free the previous PES packet. */
p_next = p_fifo->p_first->p_next;
p_fifo->p_first->p_next = NULL;
p_fifo->pf_delete_pes( p_fifo->p_packets_mgt, p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
DECODER_FIFO_START( *p_fifo ) ); p_fifo->p_first );
DECODER_FIFO_INCSTART( *p_fifo ); p_fifo->p_first = p_next;
p_fifo->i_depth--;
if( DECODER_FIFO_ISEMPTY( *p_fifo ) ) if( p_fifo->p_first == NULL )
{ {
/* No PES in the FIFO. p_last is no longer valid. */
p_fifo->pp_last = &p_fifo->p_first;
/* Signal the input thread we're waiting. */ /* Signal the input thread we're waiting. */
vlc_cond_signal( &p_fifo->data_wait ); vlc_cond_signal( &p_fifo->data_wait );
...@@ -310,7 +335,7 @@ static void ESNextDataPacket( bit_stream_t * p_bit_stream ) ...@@ -310,7 +335,7 @@ static void ESNextDataPacket( bit_stream_t * p_bit_stream )
} }
/* The next byte could be found in the next PES packet */ /* The next byte could be found in the next PES packet */
p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first; p_bit_stream->p_data = p_fifo->p_first->p_first;
vlc_mutex_unlock( &p_fifo->data_lock ); vlc_mutex_unlock( &p_fifo->data_lock );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_es.h: thread structure of the ES plugin * input_es.h: thread structure of the ES plugin
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: input_es.h,v 1.2 2001/06/27 09:53:56 massiot Exp $ * $Id: input_es.h,v 1.2.2.1 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: * Authors:
* *
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#define NB_DATA 8192
#define NB_PES 4096
#define ES_PACKET_SIZE 2048 #define ES_PACKET_SIZE 2048
#define MAX_PACKETS_IN_FIFO 14 #define ES_READ_ONCE 50
#define MAX_PACKETS_IN_FIFO 50
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ps.c: PS demux and packet management * input_ps.c: PS demux and packet management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_ps.c,v 1.44 2001/12/07 18:33:07 sam Exp $ * $Id: input_ps.c,v 1.44.2.1 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr> * Cyril Deguet <asmax@via.ecp.fr>
...@@ -86,15 +86,25 @@ static __inline__ off_t fseeko( FILE *p_file, off_t i_offset, int i_pos ) ...@@ -86,15 +86,25 @@ static __inline__ off_t fseeko( FILE *p_file, off_t i_offset, int i_pos )
*****************************************************************************/ *****************************************************************************/
static int PSProbe ( probedata_t * ); static int PSProbe ( probedata_t * );
static int PSRead ( struct input_thread_s *, static int PSRead ( struct input_thread_s *,
data_packet_t * p_packets[INPUT_READ_ONCE] ); data_packet_t ** );
static void PSInit ( struct input_thread_s * ); static void PSInit ( struct input_thread_s * );
static void PSEnd ( struct input_thread_s * ); static void PSEnd ( struct input_thread_s * );
static int PSSetProgram ( struct input_thread_s * , pgrm_descriptor_t * ); static int PSSetProgram ( struct input_thread_s * , pgrm_descriptor_t * );
static void PSSeek ( struct input_thread_s *, off_t ); static void PSSeek ( struct input_thread_s *, off_t );
static struct pes_packet_s * NewPES ( void * );
static struct data_packet_s * NewPacket ( void *, size_t ); /*****************************************************************************
static void DeletePacket ( void *, struct data_packet_s * ); * Declare a buffer manager
static void DeletePES ( void *, struct pes_packet_s * ); *****************************************************************************/
#define FLAGS BUFFERS_NOFLAGS
#define NB_LIFO 2
DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 300 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 300 );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
...@@ -113,10 +123,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -113,10 +123,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_program = PSSetProgram; input.pf_set_program = PSSetProgram;
input.pf_read = PSRead; input.pf_read = PSRead;
input.pf_demux = input_DemuxPS; input.pf_demux = input_DemuxPS;
input.pf_new_packet = NewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = NewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = DeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = DeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = NULL; input.pf_rewind = NULL;
input.pf_seek = PSSeek; input.pf_seek = PSSeek;
#undef input #undef input
...@@ -158,65 +168,12 @@ static int PSProbe( probedata_t *p_data ) ...@@ -158,65 +168,12 @@ static int PSProbe( probedata_t *p_data )
*****************************************************************************/ *****************************************************************************/
static void PSInit( input_thread_t * p_input ) static void PSInit( input_thread_t * p_input )
{ {
packet_cache_t * p_packet_cache; if( (p_input->p_method_data = input_BuffersInit()) == NULL )
/* creates the packet cache structure */
p_packet_cache = malloc( sizeof(packet_cache_t) );
if ( p_packet_cache == NULL )
{ {
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
p_input->p_method_data = (void *)p_packet_cache;
/* Initialize packet cache mutex */
vlc_mutex_init( &p_packet_cache->lock );
/* allocates the data cache */
p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE *
sizeof(data_packet_t*) );
if ( p_packet_cache->data.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->data.l_index = 0;
/* allocates the PES cache */
p_packet_cache->pes.p_stack = malloc( PES_CACHE_SIZE *
sizeof(pes_packet_t*) );
if ( p_packet_cache->pes.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->pes.l_index = 0;
/* allocates the small buffer cache */
p_packet_cache->smallbuffer.p_stack = malloc( SMALL_CACHE_SIZE *
sizeof(packet_buffer_t) );
if ( p_packet_cache->smallbuffer.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->smallbuffer.l_index = 0;
/* allocates the large buffer cache */
p_packet_cache->largebuffer.p_stack = malloc( LARGE_CACHE_SIZE *
sizeof(packet_buffer_t) );
if ( p_packet_cache->largebuffer.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->largebuffer.l_index = 0;
if( p_input->p_stream == NULL ) if( p_input->p_stream == NULL )
{ {
/* Re-open the socket as a buffered FILE stream */ /* Re-open the socket as a buffered FILE stream */
...@@ -225,6 +182,7 @@ static void PSInit( input_thread_t * p_input ) ...@@ -225,6 +182,7 @@ static void PSInit( input_thread_t * p_input )
if( p_input->p_stream == NULL ) if( p_input->p_stream == NULL )
{ {
intf_ErrMsg( "Cannot open file (%s)", strerror(errno) ); intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
...@@ -253,11 +211,22 @@ static void PSInit( input_thread_t * p_input ) ...@@ -253,11 +211,22 @@ static void PSInit( input_thread_t * p_input )
while( !p_input->b_die && !p_input->b_error while( !p_input->b_die && !p_input->b_error
&& !p_demux_data->b_has_PSM ) && !p_demux_data->b_has_PSM )
{ {
int i_result, i; int i_result;
data_packet_t * pp_packets[INPUT_READ_ONCE]; data_packet_t * p_data;
data_packet_t * p_saved_data;
i_result = PSRead( p_input, pp_packets ); i_result = PSRead( p_input, &p_data );
if( i_result == 1 ) p_saved_data = p_data;
while( p_data != NULL )
{
input_ParsePS( p_input, p_data );
p_data = p_data->p_next;
}
p_input->pf_delete_packet( p_input->p_method_data, p_saved_data );
if( i_result == 0 )
{ {
/* EOF */ /* EOF */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -265,19 +234,12 @@ static void PSInit( input_thread_t * p_input ) ...@@ -265,19 +234,12 @@ static void PSInit( input_thread_t * p_input )
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
break; break;
} }
if( i_result == -1 ) else if( i_result == -1 )
{ {
p_input->b_error = 1; p_input->b_error = 1;
break; break;
} }
for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
{
/* FIXME: use i_p_config_t */
input_ParsePS( p_input, pp_packets[i] );
DeletePacket( p_input->p_method_data, pp_packets[i] );
}
/* File too big. */ /* File too big. */
if( p_input->stream.p_selected_area->i_tell > if( p_input->stream.p_selected_area->i_tell >
INPUT_PREPARSE_LENGTH ) INPUT_PREPARSE_LENGTH )
...@@ -388,22 +350,7 @@ static void PSInit( input_thread_t * p_input ) ...@@ -388,22 +350,7 @@ static void PSInit( input_thread_t * p_input )
*****************************************************************************/ *****************************************************************************/
static void PSEnd( input_thread_t * p_input ) static void PSEnd( input_thread_t * p_input )
{ {
#define p_packet_cache ((packet_cache_t *)p_input->p_method_data) input_BuffersEnd( p_input->p_method_data );
vlc_mutex_destroy( &p_packet_cache->lock );
if( p_packet_cache->data.p_stack )
free( p_packet_cache->data.p_stack );
if( p_packet_cache->pes.p_stack )
free( p_packet_cache->pes.p_stack );
if( p_packet_cache->smallbuffer.p_stack )
free( p_packet_cache->smallbuffer.p_stack );
if( p_packet_cache->largebuffer.p_stack )
free( p_packet_cache->largebuffer.p_stack );
#undef p_packet_cache
free( p_input->p_method_data );
} }
/***************************************************************************** /*****************************************************************************
...@@ -418,7 +365,7 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer, ...@@ -418,7 +365,7 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
{ {
if( feof( p_input->p_stream ) ) if( feof( p_input->p_stream ) )
{ {
return( 1 ); return( 0 );
} }
if( (i_error = ferror( p_input->p_stream )) ) if( (i_error = ferror( p_input->p_stream )) )
...@@ -430,28 +377,29 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer, ...@@ -430,28 +377,29 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell += i_len; p_input->stream.p_selected_area->i_tell += i_len;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 0 ); return( i_len );
} }
/***************************************************************************** /*****************************************************************************
* PSRead: reads data packets * PSRead: reads data packets
***************************************************************************** *****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* EOF. * packets.
*****************************************************************************/ *****************************************************************************/
static int PSRead( input_thread_t * p_input, static int PSRead( input_thread_t * p_input,
data_packet_t * pp_packets[INPUT_READ_ONCE] ) data_packet_t ** pp_data )
{ {
byte_t p_header[6]; byte_t p_header[6];
data_packet_t * p_data; data_packet_t * p_data;
size_t i_packet_size; size_t i_packet_size;
int i_packet, i_error; int i_packet, i_error;
memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) ); *pp_data = NULL;
for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
for( i_packet = 0; i_packet < PS_READ_ONCE; i_packet++ )
{ {
/* Read what we believe to be a packet header. */ /* Read what we believe to be a packet header. */
if( (i_error = SafeRead( p_input, p_header, 4 )) ) if( (i_error = SafeRead( p_input, p_header, 4 )) <= 0 )
{ {
return( i_error ); return( i_error );
} }
...@@ -480,7 +428,7 @@ static int PSRead( input_thread_t * p_input, ...@@ -480,7 +428,7 @@ static int PSRead( input_thread_t * p_input,
} }
else else
{ {
return( 1 ); return( 0 );
} }
} }
/* Packet found. */ /* Packet found. */
...@@ -491,7 +439,7 @@ static int PSRead( input_thread_t * p_input, ...@@ -491,7 +439,7 @@ static int PSRead( input_thread_t * p_input,
if( U32_AT(p_header) != 0x1B9 ) if( U32_AT(p_header) != 0x1B9 )
{ {
/* The packet is at least 6 bytes long. */ /* The packet is at least 6 bytes long. */
if( (i_error = SafeRead( p_input, p_header + 4, 2 )) ) if( (i_error = SafeRead( p_input, p_header + 4, 2 )) <= 0 )
{ {
return( i_error ); return( i_error );
} }
...@@ -528,7 +476,8 @@ static int PSRead( input_thread_t * p_input, ...@@ -528,7 +476,8 @@ static int PSRead( input_thread_t * p_input,
} }
/* Fetch a packet of the appropriate size. */ /* Fetch a packet of the appropriate size. */
p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 ); p_data = p_input->pf_new_packet( p_input->p_method_data,
i_packet_size + 6 );
if( p_data == NULL ) if( p_data == NULL )
{ {
intf_ErrMsg( "Out of memory" ); intf_ErrMsg( "Out of memory" );
...@@ -538,25 +487,29 @@ static int PSRead( input_thread_t * p_input, ...@@ -538,25 +487,29 @@ static int PSRead( input_thread_t * p_input,
if( U32_AT(p_header) != 0x1B9 ) if( U32_AT(p_header) != 0x1B9 )
{ {
/* Copy the header we already read. */ /* Copy the header we already read. */
memcpy( p_data->p_buffer, p_header, 6 ); memcpy( p_data->p_demux_start, p_header, 6 );
/* Read the remaining of the packet. */ /* Read the remaining of the packet. */
if( i_packet_size && (i_error = if( i_packet_size && (i_error =
SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) ) SafeRead( p_input, p_data->p_demux_start + 6,
i_packet_size )) <= 0 )
{ {
p_input->pf_delete_packet( p_input->p_method_data, p_data );
return( i_error ); return( i_error );
} }
/* In MPEG-2 pack headers we still have to read stuffing bytes. */ /* In MPEG-2 pack headers we still have to read stuffing bytes. */
if( U32_AT(p_header) == 0x1BA ) if( U32_AT(p_header) == 0x1BA )
{ {
if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 ) if( i_packet_size == 8 && (p_data->p_demux_start[13] & 0x7) != 0 )
{ {
/* MPEG-2 stuffing bytes */ /* MPEG-2 stuffing bytes */
byte_t p_garbage[8]; byte_t p_garbage[8];
if( (i_error = SafeRead( p_input, p_garbage, if( (i_error = SafeRead( p_input, p_garbage,
p_data->p_buffer[13] & 0x7)) ) p_data->p_demux_start[13] & 0x7)) <= 0 )
{ {
p_input->pf_delete_packet( p_input->p_method_data,
p_data );
return( i_error ); return( i_error );
} }
} }
...@@ -565,14 +518,15 @@ static int PSRead( input_thread_t * p_input, ...@@ -565,14 +518,15 @@ static int PSRead( input_thread_t * p_input,
else else
{ {
/* Copy the small header. */ /* Copy the small header. */
memcpy( p_data->p_buffer, p_header, 4 ); memcpy( p_data->p_demux_start, p_header, 4 );
} }
/* Give the packet to the other input stages. */ /* Give the packet to the other input stages. */
pp_packets[i_packet] = p_data; *pp_data = p_data;
pp_data = &p_data->p_next;
} }
return( 0 ); return( i_packet + 1 );
} }
/***************************************************************************** /*****************************************************************************
...@@ -598,358 +552,3 @@ static void PSSeek( input_thread_t * p_input, off_t i_position ) ...@@ -598,358 +552,3 @@ static void PSSeek( input_thread_t * p_input, off_t i_position )
p_input->stream.p_selected_area->i_tell = i_position; p_input->stream.p_selected_area->i_tell = i_position;
} }
/*
* Packet management utilities
*/
/*****************************************************************************
* NewPacket: allocates a data packet
*****************************************************************************/
static struct data_packet_s * NewPacket( void * p_packet_cache,
size_t l_size )
{
packet_cache_t * p_cache;
data_packet_t * p_data;
long l_index;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "PPacket cache not initialized" );
return NULL;
}
#endif
/* Safety check */
if( l_size > INPUT_MAX_PACKET_SIZE )
{
intf_ErrMsg( "Packet too big (%d)", l_size );
return NULL;
}
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the data cache is empty */
if( p_cache->data.l_index == 0 )
{
/* Allocates a new packet */
p_data = malloc( sizeof(data_packet_t) );
if( p_data == NULL )
{
intf_ErrMsg( "Out of memory" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: data packet allocated" );
#endif
}
else
{
/* Takes the packet out from the cache */
if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ])
== NULL )
{
intf_ErrMsg( "NULL packet in the data cache" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
}
if( l_size < MAX_SMALL_SIZE )
{
/* Small buffer */
/* Checks whether the buffer cache is empty */
if( p_cache->smallbuffer.l_index == 0 )
{
/* Allocates a new packet */
p_data->p_buffer = malloc( l_size );
if( p_data->p_buffer == NULL )
{
intf_DbgMsg( "Out of memory" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: small buffer allocated" );
#endif
p_data->l_size = l_size;
}
else
{
/* Takes the packet out from the cache */
l_index = -- p_cache->smallbuffer.l_index;
if( (p_data->p_buffer = p_cache->smallbuffer.p_stack[l_index].p_data)
== NULL )
{
intf_ErrMsg( "NULL packet in the small buffer cache" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
/* Reallocates the packet if it is too small or too large */
if( p_cache->smallbuffer.p_stack[l_index].l_size < l_size ||
p_cache->smallbuffer.p_stack[l_index].l_size > 2*l_size )
{
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
p_data->l_size = l_size;
}
else
{
p_data->l_size = p_cache->smallbuffer.p_stack[l_index].l_size;
}
}
}
else
{
/* Large buffer */
/* Checks whether the buffer cache is empty */
if( p_cache->largebuffer.l_index == 0 )
{
/* Allocates a new packet */
p_data->p_buffer = malloc( l_size );
if ( p_data->p_buffer == NULL )
{
intf_ErrMsg( "Out of memory" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: large buffer allocated" );
#endif
p_data->l_size = l_size;
}
else
{
/* Takes the packet out from the cache */
l_index = -- p_cache->largebuffer.l_index;
p_data->p_buffer = p_cache->largebuffer.p_stack[l_index].p_data;
if( p_data->p_buffer == NULL )
{
intf_ErrMsg( "NULL packet in the small buffer cache" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
/* Reallocates the packet if it is too small or too large */
if( p_cache->largebuffer.p_stack[l_index].l_size < l_size ||
p_cache->largebuffer.p_stack[l_index].l_size > 2*l_size )
{
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
p_data->l_size = l_size;
}
else
{
p_data->l_size = p_cache->largebuffer.p_stack[l_index].l_size;
}
}
}
vlc_mutex_unlock( &p_cache->lock );
/* Initialize data */
p_data->p_next = NULL;
p_data->b_discard_payload = 0;
p_data->p_payload_start = p_data->p_buffer;
p_data->p_payload_end = p_data->p_buffer + l_size;
return( p_data );
}
/*****************************************************************************
* NewPES: allocates a pes packet
*****************************************************************************/
static pes_packet_t * NewPES( void * p_packet_cache )
{
packet_cache_t * p_cache;
pes_packet_t * p_pes;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return NULL;
}
#endif
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the PES cache is empty */
if( p_cache->pes.l_index == 0 )
{
/* Allocates a new packet */
p_pes = malloc( sizeof(pes_packet_t) );
if( p_pes == NULL )
{
intf_DbgMsg( "Out of memory" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: PES packet allocated" );
#endif
}
else
{
/* Takes the packet out from the cache */
p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ];
if( p_pes == NULL )
{
intf_ErrMsg( "NULL packet in the data cache" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
}
vlc_mutex_unlock( &p_cache->lock );
p_pes->b_data_alignment = p_pes->b_discontinuity =
p_pes->i_pts = p_pes->i_dts = 0;
p_pes->i_pes_size = 0;
p_pes->p_first = NULL;
return( p_pes );
}
/*****************************************************************************
* DeletePacket: deletes a data packet
*****************************************************************************/
static void DeletePacket( void * p_packet_cache,
data_packet_t * p_data )
{
packet_cache_t * p_cache;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return;
}
#endif
ASSERT( p_data );
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the data cache is full */
if ( p_cache->data.l_index < DATA_CACHE_SIZE )
{
/* Cache not full: store the packet in it */
p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
/* Small buffer or large buffer? */
if ( p_data->l_size < MAX_SMALL_SIZE )
{
/* Checks whether the small buffer cache is full */
if ( p_cache->smallbuffer.l_index < SMALL_CACHE_SIZE )
{
p_cache->smallbuffer.p_stack[
p_cache->smallbuffer.l_index ].l_size = p_data->l_size;
p_cache->smallbuffer.p_stack[
p_cache->smallbuffer.l_index++ ].p_data = p_data->p_buffer;
}
else
{
ASSERT( p_data->p_buffer );
free( p_data->p_buffer );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: small buffer freed" );
#endif
}
}
else
{
/* Checks whether the large buffer cache is full */
if ( p_cache->largebuffer.l_index < LARGE_CACHE_SIZE )
{
p_cache->largebuffer.p_stack[
p_cache->largebuffer.l_index ].l_size = p_data->l_size;
p_cache->largebuffer.p_stack[
p_cache->largebuffer.l_index++ ].p_data = p_data->p_buffer;
}
else
{
ASSERT( p_data->p_buffer );
free( p_data->p_buffer );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: large buffer freed" );
#endif
}
}
}
else
{
/* Cache full: the packet must be freed */
free( p_data->p_buffer );
free( p_data );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: data packet freed" );
#endif
}
vlc_mutex_unlock( &p_cache->lock );
}
/*****************************************************************************
* DeletePES: deletes a PES packet and associated data packets
*****************************************************************************/
static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
{
packet_cache_t * p_cache;
data_packet_t * p_data;
data_packet_t * p_next;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return;
}
#endif
ASSERT( p_pes);
p_data = p_pes->p_first;
while( p_data != NULL )
{
p_next = p_data->p_next;
DeletePacket( p_cache, p_data );
p_data = p_next;
}
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the PES cache is full */
if ( p_cache->pes.l_index < PES_CACHE_SIZE )
{
/* Cache not full: store the packet in it */
p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
}
else
{
/* Cache full: the packet must be freed */
free( p_pes );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: PES packet freed" );
#endif
}
vlc_mutex_unlock( &p_cache->lock );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ps.h: thread structure of the PS plugin * input_ps.h: thread structure of the PS plugin
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ps.h,v 1.9 2001/10/02 16:46:59 massiot Exp $ * $Id: input_ps.h,v 1.9.2.1 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr> * Cyril Deguet <asmax@via.ecp.fr>
...@@ -22,54 +22,5 @@ ...@@ -22,54 +22,5 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#define DATA_CACHE_SIZE 150 #define PS_READ_ONCE 50
#define PES_CACHE_SIZE 150
#define SMALL_CACHE_SIZE 150
#define LARGE_CACHE_SIZE 150
#define MAX_SMALL_SIZE 50 // frontier between small and large packets
typedef struct
{
data_packet_t ** p_stack;
long l_index;
} data_packet_cache_t;
typedef struct
{
pes_packet_t ** p_stack;
long l_index;
} pes_packet_cache_t;
typedef struct
{
byte_t * p_data;
long l_size;
} packet_buffer_t;
typedef struct
{
packet_buffer_t * p_stack;
long l_index;
} small_buffer_cache_t;
typedef struct
{
packet_buffer_t * p_stack;
long l_index;
} large_buffer_cache_t;
typedef struct
{
vlc_mutex_t lock;
data_packet_cache_t data;
pes_packet_cache_t pes;
small_buffer_cache_t smallbuffer;
large_buffer_cache_t largebuffer;
} packet_cache_t;
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ts.c: TS demux and netlist management * input_ts.c: TS demux and netlist management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_ts.c,v 1.42 2001/12/07 18:33:07 sam Exp $ * $Id: input_ts.c,v 1.42.2.1 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Henri Fallon <henri@videolan.org> * Authors: Henri Fallon <henri@videolan.org>
* *
...@@ -89,7 +89,21 @@ static int TSProbe ( probedata_t * ); ...@@ -89,7 +89,21 @@ static int TSProbe ( probedata_t * );
static void TSInit ( struct input_thread_s * ); static void TSInit ( struct input_thread_s * );
static void TSEnd ( struct input_thread_s * ); static void TSEnd ( struct input_thread_s * );
static int TSRead ( struct input_thread_s *, static int TSRead ( struct input_thread_s *,
data_packet_t * p_packets[INPUT_READ_ONCE] ); data_packet_t ** );
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_UNIQUE_SIZE
#define NB_LIFO 1
DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 1000 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_TOIO( FLAGS, TS_PACKET_SIZE );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
...@@ -108,10 +122,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -108,10 +122,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_program = input_SetProgram; input.pf_set_program = input_SetProgram;
input.pf_read = TSRead; input.pf_read = TSRead;
input.pf_demux = input_DemuxTS; input.pf_demux = input_DemuxTS;
input.pf_new_packet = input_NetlistNewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NetlistNewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_NetlistDeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_NetlistDeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = NULL; input.pf_rewind = NULL;
input.pf_seek = NULL; input.pf_seek = NULL;
#undef input #undef input
...@@ -160,7 +174,6 @@ static int TSProbe( probedata_t * p_data ) ...@@ -160,7 +174,6 @@ static int TSProbe( probedata_t * p_data )
*****************************************************************************/ *****************************************************************************/
static void TSInit( input_thread_t * p_input ) static void TSInit( input_thread_t * p_input )
{ {
/* Initialize netlist and TS structures */
thread_ts_data_t * p_method; thread_ts_data_t * p_method;
es_descriptor_t * p_pat_es; es_descriptor_t * p_pat_es;
es_ts_data_t * p_demux_data; es_ts_data_t * p_demux_data;
...@@ -184,11 +197,9 @@ static void TSInit( input_thread_t * p_input ) ...@@ -184,11 +197,9 @@ static void TSInit( input_thread_t * p_input )
p_input->p_method_data = NULL; p_input->p_method_data = NULL;
/* Initialize netlist */ if( (p_input->p_method_data = input_BuffersInit()) == NULL )
if( input_NetlistInit( p_input, NB_DATA, NB_DATA, NB_PES, TS_PACKET_SIZE,
INPUT_READ_ONCE ) )
{ {
intf_ErrMsg( "TS input : Could not initialize netlist" ); p_input->b_error = 1;
return; return;
} }
...@@ -227,23 +238,23 @@ static void TSEnd( input_thread_t * p_input ) ...@@ -227,23 +238,23 @@ static void TSEnd( input_thread_t * p_input )
input_DelES( p_input, p_pat_es ); input_DelES( p_input, p_pat_es );
free(p_input->p_plugin_data); free(p_input->p_plugin_data);
input_NetlistEnd( p_input ); input_BuffersEnd( p_input->p_method_data );
} }
/***************************************************************************** /*****************************************************************************
* TSRead: reads data packets * TSRead: reads data packets
***************************************************************************** *****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* EOF. * packets.
*****************************************************************************/ *****************************************************************************/
static int TSRead( input_thread_t * p_input, static int TSRead( input_thread_t * p_input,
data_packet_t * pp_packets[INPUT_READ_ONCE] ) data_packet_t ** pp_data )
{ {
thread_ts_data_t * p_method; thread_ts_data_t * p_method;
unsigned int i_loop; int i_read = 0, i_loop;
int i_read;
int i_data = 1; int i_data = 1;
struct iovec * p_iovec; struct iovec p_iovec[TS_READ_ONCE];
data_packet_t * p_data;
struct timeval timeout; struct timeval timeout;
/* Init */ /* Init */
...@@ -257,9 +268,6 @@ static int TSRead( input_thread_t * p_input, ...@@ -257,9 +268,6 @@ static int TSRead( input_thread_t * p_input,
timeout.tv_sec = 0; timeout.tv_sec = 0;
timeout.tv_usec = 500000; timeout.tv_usec = 500000;
/* Reset pointer table */
memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
/* Fill if some data is available */ /* Fill if some data is available */
#if defined( WIN32 ) #if defined( WIN32 )
if ( ! p_input->stream.b_pace_control ) if ( ! p_input->stream.b_pace_control )
...@@ -278,25 +286,26 @@ static int TSRead( input_thread_t * p_input, ...@@ -278,25 +286,26 @@ static int TSRead( input_thread_t * p_input,
if( i_data ) if( i_data )
{ {
/* Get iovecs */ /* Get iovecs */
p_iovec = input_NetlistGetiovec( p_input->p_method_data ); *pp_data = p_data = input_BuffersToIO( p_input->p_method_data, p_iovec,
TS_READ_ONCE );
if ( p_iovec == NULL ) if ( p_data == NULL )
{ {
return( -1 ); /* empty netlist */ return( -1 );
} }
#if defined( WIN32 ) #if defined( WIN32 )
if( p_input->stream.b_pace_control ) if( p_input->stream.b_pace_control )
{ {
i_read = readv( p_input->i_handle, p_iovec, INPUT_READ_ONCE ); i_read = readv( p_input->i_handle, p_iovec, TS_READ_ONCE );
} }
else else
{ {
i_read = readv_network( p_input->i_handle, p_iovec, i_read = readv_network( p_input->i_handle, p_iovec,
INPUT_READ_ONCE, p_method ); TS_READ_ONCE, p_method );
} }
#else #else
i_read = readv( p_input->i_handle, p_iovec, INPUT_READ_ONCE ); i_read = readv( p_input->i_handle, p_iovec, TS_READ_ONCE );
/* Shouldn't happen, but it does - at least under Linux */ /* Shouldn't happen, but it does - at least under Linux */
if( (i_read == -1) && ( (errno == EAGAIN) || (errno = EWOULDBLOCK) ) ) if( (i_read == -1) && ( (errno == EAGAIN) || (errno = EWOULDBLOCK) ) )
...@@ -306,36 +315,35 @@ static int TSRead( input_thread_t * p_input, ...@@ -306,36 +315,35 @@ static int TSRead( input_thread_t * p_input,
i_read = 0; i_read = 0;
} }
#endif #endif
/* Error */
if( i_read == -1 ) if( i_read == -1 )
{ {
intf_ErrMsg( "input error: TS readv error" ); intf_ErrMsg( "input error: TS readv error" );
p_input->pf_delete_packet( p_input->p_method_data, p_data );
return( -1 ); return( -1 );
} }
p_input->stream.p_selected_area->i_tell += i_read;
i_read /= TS_PACKET_SIZE;
/* EOF */ /* Check correct TS header */
if( i_read == 0 && p_input->stream.b_seekable ) for( i_loop = 0; i_loop < i_read; i_loop++ )
{
return( 1 );
}
input_NetlistMviovec( p_input->p_method_data,
(int)(((i_read-1)/TS_PACKET_SIZE)+1) , pp_packets );
/* check correct TS header */
for( i_loop=0; i_loop * TS_PACKET_SIZE < i_read; i_loop++ )
{ {
if( pp_packets[i_loop]->p_buffer[0] != 0x47 ) if( (*pp_data)->p_demux_start[0] != 0x47 )
{
intf_ErrMsg( "input error: bad TS packet (starts with " intf_ErrMsg( "input error: bad TS packet (starts with "
"0x%.2x, should be 0x47)", "0x%.2x, should be 0x47)",
pp_packets[i_loop]->p_buffer[0] ); p_data->p_demux_start[0] );
}
pp_data = &(*pp_data)->p_next;
} }
for( ; i_loop < INPUT_READ_ONCE ; i_loop++ )
if( i_read != TS_READ_ONCE )
{ {
pp_packets[i_loop] = NULL; /* Delete remaining packets */
p_input->pf_delete_packet( p_input->p_method_data, *pp_data );
*pp_data = NULL;
} }
p_input->stream.p_selected_area->i_tell += i_read;
} }
return 0; return( i_read );
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ts.h: structures of the input not exported to other modules * input_ts.h: structures of the input not exported to other modules
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ts.h,v 1.12.2.1 2001/12/09 21:14:19 sam Exp $ * $Id: input_ts.h,v 1.12.2.2 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Henri Fallon <henri@via.ecp.fr> * Authors: Henri Fallon <henri@via.ecp.fr>
* Boris Dors <babal@via.ecp.fr> * Boris Dors <babal@via.ecp.fr>
...@@ -22,10 +22,12 @@ ...@@ -22,10 +22,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#define NB_DATA 16384 /* UDP packets contain 1500 bytes, that is 7 TS packets */
#define NB_PES 8192 #define TS_READ_ONCE 7
#define BUFFER_SIZE (7 * TS_PACKET_SIZE) #ifdef WIN32
# define BUFFER_SIZE (7 * TS_PACKET_SIZE)
#endif
/***************************************************************************** /*****************************************************************************
* thread_ts_data_t: private input data * thread_ts_data_t: private input data
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg_adec.c: MPEG audio decoder thread * mpeg_adec.c: MPEG audio decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: mpeg_adec.c,v 1.5.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: mpeg_adec.c,v 1.5.2.2 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Michel Kaempf <maxx@via.ecp.fr> * Authors: Michel Kaempf <maxx@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr> * Michel Lespinasse <walken@via.ecp.fr>
...@@ -203,11 +203,11 @@ static void DecodeThread( adec_thread_t * p_adec ) ...@@ -203,11 +203,11 @@ static void DecodeThread( adec_thread_t * p_adec )
buffer = ((s16 *)p_adec->p_aout_fifo->buffer) buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
+ (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE); + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
if( DECODER_FIFO_START( *p_adec->p_fifo)->i_pts ) if( p_adec->p_fifo->p_first->i_pts )
{ {
p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] = p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
DECODER_FIFO_START( *p_adec->p_fifo )->i_pts; p_adec->p_fifo->p_first->i_pts;
DECODER_FIFO_START(*p_adec->p_fifo)->i_pts = 0; p_adec->p_fifo->p_first->i_pts = 0;
} }
else else
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* video_parser.c : video parser thread * video_parser.c : video parser thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: video_parser.c,v 1.6.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: video_parser.c,v 1.6.2.2 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr> * Samuel Hocevar <sam@via.ecp.fr>
...@@ -281,38 +281,6 @@ static int InitThread( vpar_thread_t *p_vpar ) ...@@ -281,38 +281,6 @@ static int InitThread( vpar_thread_t *p_vpar )
return( 0 ); return( 0 );
} }
/*****************************************************************************
* mpeg_vdec_ErrorThread: RunThread() error loop
*****************************************************************************
* This function is called when an error occured during thread main's loop. The
* thread can still receive feed, but must be ready to terminate as soon as
* possible.
*****************************************************************************/
static void mpeg_vdec_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->p_fifo->data_lock );
/* Wait until a `die' order is sent */
while( !p_vpar->p_fifo->b_die )
{
/* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY(*p_vpar->p_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->p_fifo->data_wait, &p_vpar->p_fifo->data_lock );
}
/* We can release the lock before leaving */
vlc_mutex_unlock( &p_vpar->p_fifo->data_lock );
}
/***************************************************************************** /*****************************************************************************
* EndThread: thread destruction * EndThread: thread destruction
***************************************************************************** *****************************************************************************
...@@ -428,13 +396,13 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream, ...@@ -428,13 +396,13 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream,
if( b_new_pes ) if( b_new_pes )
{ {
p_vpar->sequence.next_pts = p_vpar->sequence.next_pts =
DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts; p_bit_stream->p_decoder_fifo->p_first->i_pts;
p_vpar->sequence.next_dts = p_vpar->sequence.next_dts =
DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_dts; p_bit_stream->p_decoder_fifo->p_first->i_dts;
p_vpar->sequence.i_current_rate = p_vpar->sequence.i_current_rate =
DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_rate; p_bit_stream->p_decoder_fifo->p_first->i_rate;
if( DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->b_discontinuity ) if( p_bit_stream->p_decoder_fifo->p_first->b_discontinuity )
{ {
#ifdef TRACE_VPAR #ifdef TRACE_VPAR
intf_DbgMsg( "Discontinuity in BitstreamCallback" ); intf_DbgMsg( "Discontinuity in BitstreamCallback" );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* spu_decoder.c : spu decoder thread * spu_decoder.c : spu decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: spu_decoder.c,v 1.5.2.2 2001/12/30 06:06:00 sam Exp $ * $Id: spu_decoder.c,v 1.5.2.3 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -275,7 +275,7 @@ static void ParsePacket( spudec_thread_t *p_spudec ) ...@@ -275,7 +275,7 @@ static void ParsePacket( spudec_thread_t *p_spudec )
p_spudec->i_spu_size ); p_spudec->i_spu_size );
/* We cannot display a subpicture with no date */ /* We cannot display a subpicture with no date */
if( DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts == 0 ) if( p_spudec->p_fifo->p_first->i_pts == 0 )
{ {
intf_WarnMsg( 3, "spudec error: subtitle without a date" ); intf_WarnMsg( 3, "spudec error: subtitle without a date" );
return; return;
...@@ -295,7 +295,7 @@ static void ParsePacket( spudec_thread_t *p_spudec ) ...@@ -295,7 +295,7 @@ static void ParsePacket( spudec_thread_t *p_spudec )
} }
/* Get display time now. If we do it later, we may miss the PTS. */ /* Get display time now. If we do it later, we may miss the PTS. */
p_spudec->i_pts = DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts; p_spudec->i_pts = p_spudec->p_fifo->p_first->i_pts;
/* Allocate the temporary buffer we will parse */ /* Allocate the temporary buffer we will parse */
p_src = malloc( p_spudec->i_rle_size ); p_src = malloc( p_spudec->i_rle_size );
......
...@@ -70,17 +70,14 @@ ...@@ -70,17 +70,14 @@
#include "modules.h" #include "modules.h"
#include "modules_export.h" #include "modules_export.h"
#include "../mpeg/input_ps.h"
#include "input_vcd.h" #include "input_vcd.h"
#include "linux_cdrom_tools.h" #include "linux_cdrom_tools.h"
/* how many blocks VCDRead will read in each loop */ /* how many blocks VCDRead will read in each loop */
#define VCD_BLOCKS_ONCE 64 #define VCD_BLOCKS_ONCE 4
#define VCD_DATA_ONCE (2 * VCD_BLOCKS_ONCE) #define VCD_DATA_ONCE (2 * VCD_BLOCKS_ONCE)
#define BUFFER_SIZE VCD_DATA_SIZE #define BUFFER_SIZE VCD_DATA_SIZE
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -95,11 +92,19 @@ static void VCDClose ( struct input_thread_s *); ...@@ -95,11 +92,19 @@ static void VCDClose ( struct input_thread_s *);
static void VCDEnd ( struct input_thread_s *); static void VCDEnd ( struct input_thread_s *);
static void VCDSeek ( struct input_thread_s *, off_t ); static void VCDSeek ( struct input_thread_s *, off_t );
static int VCDRewind ( struct input_thread_s * ); static int VCDRewind ( struct input_thread_s * );
static struct data_packet_s * NewPacket( void *, size_t );
static pes_packet_t * NewPES ( void * );
static void DeletePacket ( void *, data_packet_t * );
static void DeletePES ( void *, pes_packet_t *);
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_NOFLAGS
#define NB_LIFO 2
DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 1000 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 1000 );
/***************************************************************************** /*****************************************************************************
...@@ -119,10 +124,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -119,10 +124,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_area = VCDSetArea; input.pf_set_area = VCDSetArea;
input.pf_set_program = VCDSetProgram; input.pf_set_program = VCDSetProgram;
input.pf_demux = input_DemuxPS; input.pf_demux = input_DemuxPS;
input.pf_new_packet = NewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = NewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = DeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = DeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = VCDRewind; input.pf_rewind = VCDRewind;
input.pf_seek = VCDSeek; input.pf_seek = VCDSeek;
#undef input #undef input
...@@ -162,8 +167,6 @@ static int VCDProbe( probedata_t *p_data ) ...@@ -162,8 +167,6 @@ static int VCDProbe( probedata_t *p_data )
*****************************************************************************/ *****************************************************************************/
static void VCDOpen( struct input_thread_s *p_input ) static void VCDOpen( struct input_thread_s *p_input )
{ {
int vcdhandle;
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
/* If we are here we can control the pace... */ /* If we are here we can control the pace... */
...@@ -171,7 +174,6 @@ static void VCDOpen( struct input_thread_s *p_input ) ...@@ -171,7 +174,6 @@ static void VCDOpen( struct input_thread_s *p_input )
p_input->stream.b_seekable = 1; p_input->stream.b_seekable = 1;
p_input->stream.p_selected_area->i_size = 0; p_input->stream.p_selected_area->i_size = 0;
p_input->stream.p_selected_area->i_tell = 0; p_input->stream.p_selected_area->i_tell = 0;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
...@@ -181,20 +183,17 @@ static void VCDOpen( struct input_thread_s *p_input ) ...@@ -181,20 +183,17 @@ static void VCDOpen( struct input_thread_s *p_input )
if( strlen( p_input->p_source ) > 4 if( strlen( p_input->p_source ) > 4
&& !strncasecmp( p_input->p_source, "vcd:", 4 ) ) && !strncasecmp( p_input->p_source, "vcd:", 4 ) )
{ {
vcdhandle = open( p_input->p_source + 4, O_RDONLY | O_NONBLOCK ); p_input->i_handle = open( p_input->p_source + 4, O_RDONLY | O_NONBLOCK );
} }
else else
{ {
vcdhandle = open( p_input->p_source + 4, O_RDONLY | O_NONBLOCK ); p_input->i_handle = open( p_input->p_source + 4, O_RDONLY | O_NONBLOCK );
} }
if( vcdhandle == -1 ) if( p_input->i_handle == -1 )
{ {
p_input->b_error = 1; p_input->b_error = 1;
return;
} }
p_input->i_handle = (int) vcdhandle;
} }
/***************************************************************************** /*****************************************************************************
...@@ -216,10 +215,9 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -216,10 +215,9 @@ static void VCDInit( input_thread_t * p_input )
int i; int i;
input_area_t * p_area; input_area_t * p_area;
es_descriptor_t * p_es; es_descriptor_t * p_es;
packet_cache_t * p_packet_cache;
p_vcd = malloc( sizeof(thread_vcd_data_t) ); p_vcd = malloc( sizeof(thread_vcd_data_t) );
if( p_vcd == NULL ) if( p_vcd == NULL )
{ {
intf_ErrMsg( "vcd error: out of memory" ); intf_ErrMsg( "vcd error: out of memory" );
...@@ -227,78 +225,35 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -227,78 +225,35 @@ static void VCDInit( input_thread_t * p_input )
return; return;
} }
p_input->p_plugin_data = (void *)p_vcd; p_input->p_plugin_data = (void *)p_vcd;
p_input->p_method_data = NULL;
p_vcd->vcdhandle = p_input->i_handle; if( (p_input->p_method_data = input_BuffersInit()) == NULL )
p_vcd->b_end_of_track = 0;
/* we read the Table Of Content information */
if ( read_toc(p_vcd) == -1 )
{
intf_ErrMsg("An error occured when reading vcd's TOC");
}
p_input->i_read_once = VCD_DATA_ONCE;
p_packet_cache = malloc( sizeof(packet_cache_t) );
if ( p_packet_cache == NULL )
{ {
intf_ErrMsg( "vcd error: out of memory" ); free( p_vcd );
p_input->b_error = 1;
return;
}
p_input->p_method_data = (void *)p_packet_cache;
/* Initialize packet cache mutex */
vlc_mutex_init( &p_packet_cache->lock );
/* allocates the data cache */
p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE *
sizeof(data_packet_t*) );
if ( p_packet_cache->data.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
p_packet_cache->data.l_index = 0;
p_vcd->i_handle = p_input->i_handle;
/* allocates the PES cache */
p_packet_cache->pes.p_stack = malloc( PES_CACHE_SIZE * /* We read the Table Of Content information */
sizeof(pes_packet_t*) ); p_vcd->nb_tracks = ioctl_GetTrackCount( p_input->i_handle );
if ( p_packet_cache->pes.p_stack == NULL ) if( p_vcd->nb_tracks < 0 )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->pes.l_index = 0;
/* allocates the small buffer cache */
p_packet_cache->smallbuffer.p_stack = malloc( SMALL_CACHE_SIZE *
sizeof(packet_buffer_t) );
if ( p_packet_cache->smallbuffer.p_stack == NULL )
{ {
intf_ErrMsg( "Out of memory" ); input_BuffersEnd( p_input->p_method_data );
free( p_vcd );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
p_packet_cache->smallbuffer.l_index = 0;
p_vcd->p_sectors = ioctl_GetSectors( p_input->i_handle );
/* allocates the large buffer cache */ if ( p_vcd->p_sectors == NULL )
p_packet_cache->largebuffer.p_stack = malloc( LARGE_CACHE_SIZE *
sizeof(packet_buffer_t) );
if ( p_packet_cache->largebuffer.p_stack == NULL )
{ {
intf_ErrMsg( "Out of memory" ); input_BuffersEnd( p_input->p_method_data );
free( p_vcd );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
p_packet_cache->largebuffer.l_index = 0;
/* Set stream and area data */ /* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -309,7 +264,6 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -309,7 +264,6 @@ static void VCDInit( input_thread_t * p_input )
/* disc input method */ /* disc input method */
p_input->stream.i_method = INPUT_METHOD_VCD; p_input->stream.i_method = INPUT_METHOD_VCD;
#define area p_input->stream.pp_areas #define area p_input->stream.pp_areas
for( i = 1 ; i <= p_vcd->nb_tracks - 1 ; i++ ) for( i = 1 ; i <= p_vcd->nb_tracks - 1 ; i++ )
{ {
...@@ -319,8 +273,9 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -319,8 +273,9 @@ static void VCDInit( input_thread_t * p_input )
area[i]->i_id = i; area[i]->i_id = i;
/* Absolute start offset and size */ /* Absolute start offset and size */
area[i]->i_start = p_vcd->tracks_sector[i]; area[i]->i_start = (off_t)p_vcd->p_sectors[i] * (off_t)VCD_DATA_SIZE;
area[i]->i_size = p_vcd->tracks_sector[i+1] - p_vcd->tracks_sector[i]; area[i]->i_size = (off_t)(p_vcd->p_sectors[i+1] - p_vcd->p_sectors[i])
* (off_t)VCD_DATA_SIZE;
/* Number of chapters */ /* Number of chapters */
area[i]->i_part_nb = 0; // will be the entry points area[i]->i_part_nb = 0; // will be the entry points
...@@ -330,19 +285,19 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -330,19 +285,19 @@ static void VCDInit( input_thread_t * p_input )
area[i]->i_angle_nb = 1; // no angle support in VCDs area[i]->i_angle_nb = 1; // no angle support in VCDs
area[i]->i_angle = 1; area[i]->i_angle = 1;
area[i]->i_plugin_data = p_vcd->tracks_sector[i]; area[i]->i_plugin_data = p_vcd->p_sectors[i];
} }
#undef area #undef area
/* Get requested title - if none try the first title */ /* Get requested title - if none try the first title */
i_title = main_GetIntVariable( INPUT_TITLE_VAR, 1 ); i_title = main_GetIntVariable( INPUT_TITLE_VAR, 1 );
if( i_title <= 0) if( i_title <= 0 )
{ {
i_title = 1; i_title = 1;
} }
// p_vcd->current_track = i_title-1 ; // p_vcd->i_track = i_title-1;
/* Get requested chapter - if none defaults to first one */ /* Get requested chapter - if none defaults to first one */
i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 ); i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 );
if( i_chapter <= 0 ) if( i_chapter <= 0 )
...@@ -350,7 +305,6 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -350,7 +305,6 @@ static void VCDInit( input_thread_t * p_input )
i_chapter = 1; i_chapter = 1;
} }
p_input->stream.pp_areas[i_title]->i_part = i_chapter; p_input->stream.pp_areas[i_title]->i_part = i_chapter;
p_area = p_input->stream.pp_areas[i_title]; p_area = p_input->stream.pp_areas[i_title];
...@@ -362,38 +316,33 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -362,38 +316,33 @@ static void VCDInit( input_thread_t * p_input )
input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) ); input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
p_input->stream.p_selected_program = p_input->stream.pp_programs[0]; p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
/* No PSM to read in disc mode, we already have all information */ /* No PSM to read in disc mode, we already have all the information */
p_input->stream.p_selected_program->b_is_ok = 1; p_input->stream.p_selected_program->b_is_ok = 1;
p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xe0, 0 ); p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xe0, 0 );
p_es->i_stream_id = 0xe0; p_es->i_stream_id = 0xe0;
p_es->i_type = MPEG1_VIDEO_ES; p_es->i_type = MPEG1_VIDEO_ES;
p_es->i_cat = VIDEO_ES; p_es->i_cat = VIDEO_ES;
if( p_main->b_video ) if( p_main->b_video )
{ {
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
} }
p_es = input_AddES( p_input, p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xc0, 0 );
p_input->stream.p_selected_program, 0xc0, 0 );
p_es->i_stream_id = 0xc0; p_es->i_stream_id = 0xc0;
p_es->i_type = MPEG1_AUDIO_ES; p_es->i_type = MPEG1_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
p_es->i_cat = AUDIO_ES; p_es->i_cat = AUDIO_ES;
if( p_main->b_audio ) if( p_main->b_audio )
{ {
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
} }
vlc_mutex_unlock( &p_input->stream.stream_lock );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return;
} }
/***************************************************************************** /*****************************************************************************
* VCDEnd: frees unused data * VCDEnd: frees unused data
*****************************************************************************/ *****************************************************************************/
...@@ -401,17 +350,18 @@ static void VCDEnd( input_thread_t * p_input ) ...@@ -401,17 +350,18 @@ static void VCDEnd( input_thread_t * p_input )
{ {
thread_vcd_data_t * p_vcd; thread_vcd_data_t * p_vcd;
input_BuffersEnd( p_input->p_method_data );
p_vcd = (thread_vcd_data_t*)p_input->p_plugin_data; p_vcd = (thread_vcd_data_t*)p_input->p_plugin_data;
free( p_vcd ); free( p_vcd );
} }
/***************************************************************************** /*****************************************************************************
* VCDSetProgram: Does nothing since a VCD is mono_program * VCDSetProgram: Does nothing since a VCD is mono_program
*****************************************************************************/ *****************************************************************************/
static int VCDSetProgram( input_thread_t * p_input, static int VCDSetProgram( input_thread_t * p_input,
pgrm_descriptor_t * p_program) pgrm_descriptor_t * p_program)
{ {
return 0; return 0;
} }
...@@ -424,132 +374,119 @@ static int VCDSetProgram( input_thread_t * p_input, ...@@ -424,132 +374,119 @@ static int VCDSetProgram( input_thread_t * p_input,
static int VCDSetArea( input_thread_t * p_input, input_area_t * p_area ) static int VCDSetArea( input_thread_t * p_input, input_area_t * p_area )
{ {
thread_vcd_data_t * p_vcd; thread_vcd_data_t * p_vcd;
p_vcd = (thread_vcd_data_t*)p_input->p_plugin_data; p_vcd = (thread_vcd_data_t*)p_input->p_plugin_data;
/* we can't use the interface slider until initilization is complete */ /* we can't use the interface slider until initilization is complete */
p_input->stream.b_seekable = 0; p_input->stream.b_seekable = 0;
if ( p_area != p_input->stream.p_selected_area ) if( p_area != p_input->stream.p_selected_area )
{ {
/* Reset the Chapter position of the old title */ /* Reset the Chapter position of the current title */
p_input->stream.p_selected_area->i_part = 0; p_input->stream.p_selected_area->i_part = 1;
p_input->stream.p_selected_area->i_tell = 0; p_input->stream.p_selected_area->i_tell = 0;
/* Change the default area */ /* Change the default area */
p_input->stream.p_selected_area = p_area; p_input->stream.p_selected_area = p_area;
/* Change the current track */ /* Change the current track */
/* The first track is not a valid one */ /* The first track is not a valid one */
p_vcd->current_track = p_area->i_id ; p_vcd->i_track = p_area->i_id;
p_vcd->current_sector = p_vcd->tracks_sector[p_vcd->current_track] ; p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track];
} }
/* warn interface that something has changed */ /* warn interface that something has changed */
p_input->stream.b_seekable = 1; p_input->stream.b_seekable = 1;
p_input->stream.b_changed = 1; p_input->stream.b_changed = 1;
return 0 ;
}
return 0;
}
/***************************************************************************** /*****************************************************************************
* VCDRead: reads from the VCD into PES packets. * VCDRead: reads from the VCD into PES packets.
***************************************************************************** *****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* EOF. * packets.
*****************************************************************************/ *****************************************************************************/
static int VCDRead( input_thread_t * p_input, static int VCDRead( input_thread_t * p_input, data_packet_t ** pp_data )
data_packet_t ** pp_packets )
{ {
thread_vcd_data_t * p_vcd; thread_vcd_data_t * p_vcd;
data_packet_t * p_data; data_packet_t * p_data;
int i_packet_size; int i_packet_size;
int i_index; int i_index;
int i_packet; int i_packet;
boolean_t b_eof; u32 i_header;
byte_t * p_buffer; byte_t p_buffer[ VCD_DATA_SIZE ];
boolean_t b_no_packet; boolean_t b_eot = 0; /* end of track */
/* boolean_t b_eoc; No chapters yet */ /* boolean_t b_eoc; No chapters yet */
p_vcd = (thread_vcd_data_t *)p_input->p_plugin_data; p_vcd = (thread_vcd_data_t *)p_input->p_plugin_data;
p_buffer = malloc ( VCD_DATA_SIZE ); i_packet = 0;
*pp_data = NULL;
if ( p_buffer == NULL ) while( i_packet < VCD_DATA_ONCE )
{ {
intf_ErrMsg("Could not malloc the read buffer"); if( ioctl_ReadSector( p_vcd->i_handle, p_vcd->i_sector, p_buffer ) )
return -1; {
} /* Read error, but assume we reached the end of the track */
b_eot = 1;
break;
}
p_vcd->i_sector++;
i_packet = 0;
b_no_packet = 0;
while( i_packet < VCD_DATA_ONCE ) if( p_vcd->i_sector >= p_vcd->p_sectors[p_vcd->i_track + 1] )
{
i_index = 0;
if ( VCD_sector_read( p_vcd, p_buffer ) == -1 )
{ {
return -1; b_eot = 1;
break;
} }
while (i_index < BUFFER_SIZE - 6) i_index = 0;
while( i_index < BUFFER_SIZE-6 && i_packet < VCD_DATA_ONCE )
{ {
i_header = U32_AT(p_buffer + i_index);
if( (U32_AT(p_buffer + i_index) & 0xFFFFFF00) != 0x100L )
/* It is common for MPEG-1 streams to pad with zeros
* (although it is forbidden by the recommendation), so
* don't bother everybody in this case. */
while( !i_header && (++i_index < BUFFER_SIZE - 4) )
{ {
/* This is not the startcode of a packet. Read the stream i_header = U32_AT(p_buffer + i_index);
* until we find one. */ }
if( !U32_AT( p_buffer + i_index ) ) if( !i_header )
{ {
/* It is common for MPEG-1 streams to pad with zeros intf_WarnMsg( 12, "vcd warning: zero-padded packet" );
* (although it is forbidden by the recommendation), so break;
* don't bother everybody in this case. */
intf_WarnMsg( 3, "Garbage at input" );
}
while( ( (U32_AT(p_buffer + i_index) & 0xFFFFFF00) != 0x100L )
&& ( i_index < BUFFER_SIZE - 4 ) )
{
i_index ++;
}
if ( i_index == BUFFER_SIZE - 4 )
{
b_no_packet = 1;
}
/* Packet found. */
} }
if (b_no_packet) /* Read the stream until we find a startcode. */
while( (i_header & 0xFFFFFF00) != 0x100L
&& (++i_index < BUFFER_SIZE - 4) )
{
i_header = U32_AT(p_buffer + i_index);
}
if( (i_header & 0xFFFFFF00) != 0x100L )
{ {
b_no_packet = 0; intf_WarnMsg( 3, "vcd warning: no packet at sector %d",
intf_WarnMsg(3, "No packet found on sector %d\n", p_vcd->i_sector - 1 );
p_vcd->current_sector -1 );
break; /* go to the next sector */ break; /* go to the next sector */
} }
#ifdef DEBUG intf_DbgMsg( "packet start code : %X", i_header );
intf_DbgMsg("packet start code : %X\n",
U32_AT(p_buffer + i_index)); switch( i_header )
#endif
/* 0x1B9 == SYSTEM_END_CODE, it is only 4 bytes long. */
if( U32_AT(p_buffer + i_index) != 0x1B9 )
{ {
/* The packet is at least 6 bytes long. */ /* 0x1b9 == SYSTEM_END_CODE, it is only 4 bytes long. */
case 0x1b9:
if( U32_AT(p_buffer + i_index) != 0x1BA ) i_packet_size = -2;
{ break;
/* That's the case for all packets, except pack header. */
i_packet_size = U16_AT((p_buffer + ( i_index + 4 ))); /* Pack header */
} case 0x1ba:
else
{
/* Pack header. */
if( ( *( p_buffer + ( i_index + 4 ) ) & 0xC0) == 0x40 ) if( ( *( p_buffer + ( i_index + 4 ) ) & 0xC0) == 0x40 )
{ {
/* MPEG-2 */ /* MPEG-2 */
...@@ -562,99 +499,99 @@ static int VCDRead( input_thread_t * p_input, ...@@ -562,99 +499,99 @@ static int VCDRead( input_thread_t * p_input,
} }
else else
{ {
intf_ErrMsg( "Unable to determine stream type" ); intf_ErrMsg( "vcd error: unable to determine "
"stream type" );
return( -1 ); return( -1 );
} }
} break;
}
else /* The packet is at least 6 bytes long. */
{ default:
/* System End Code */ /* That's the case for all packets, except pack header. */
i_packet_size = -2; i_packet_size = U16_AT((p_buffer + ( i_index + 4 )));
break;
} }
#ifdef DEBUG
intf_DbgMsg("i_index : %d\n", i_index); intf_DbgMsg( "i_index : %d", i_index );
intf_DbgMsg("i_packet_size : %d\n", i_packet_size); intf_DbgMsg( "i_packet_size : %d", i_packet_size );
#endif
if ( i_index + i_packet_size > BUFFER_SIZE ) if ( i_index + i_packet_size > BUFFER_SIZE )
{ {
intf_ErrMsg( "Too long packet"); intf_ErrMsg( "vcd error: packet too long (%i)",
i_index + i_packet_size );
continue; continue;
} }
/* Fetch a packet of the appropriate size. */ /* Fetch a packet of the appropriate size. */
p_data = p_input->pf_new_packet( p_input->p_method_data,
p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 ); i_packet_size + 6 );
if( p_data == NULL ) if( p_data == NULL )
{ {
intf_ErrMsg( "Out of memory" ); intf_ErrMsg( "vcd error: out of memory" );
return( -1 ); return( -1 );
} }
if( U32_AT(p_buffer) != 0x1B9 ) if( U32_AT(p_buffer) != 0x1B9 )
{ {
p_main->fast_memcpy( p_data->p_buffer, p_buffer + i_index, p_main->fast_memcpy( p_data->p_demux_start, p_buffer + i_index,
6 + i_packet_size ); 6 + i_packet_size );
i_index += ( 6 + i_packet_size ); i_index += ( 6 + i_packet_size );
} }
else else
{ {
/* Copy the small header. */ /* Copy the small header. */
memcpy( p_data->p_buffer, p_buffer + i_index, 4 ); memcpy( p_data->p_demux_start, p_buffer + i_index, 4 );
i_index += 4; i_index += 4;
} }
/* Give the packet to the other input stages. */ /* Give the packet to the other input stages. */
pp_packets[i_packet] = p_data; *pp_data = p_data;
i_packet ++; pp_data = &p_data->p_next;
i_packet++;
} }
if ( p_vcd->b_end_of_track )
break;
} }
pp_packets[i_packet] = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell = p_input->stream.p_selected_area->i_tell =
p_vcd->current_sector - (off_t)p_vcd->i_sector * (off_t)VCD_DATA_SIZE
p_input->stream.p_selected_area->i_start ; - p_input->stream.p_selected_area->i_start;
/* no chapter for the moment*/ /* no chapter for the moment*/
/*if( b_eoc ) #if 0
if( b_eoc )
{ {
* We modify i_part only at end of chapter not to erase /* We modify i_part only at end of chapter not to erase
* some modification from the interface * * some modification from the interface */
p_input->stream.p_selected_area->i_part = p_vcd->i_chapter; p_input->stream.p_selected_area->i_part = p_vcd->i_chapter;
}*/
b_eof = p_vcd->b_end_of_track
&& ( ( p_vcd->current_track ) >= p_vcd->nb_tracks - 1);
if( b_eof )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 1;
} }
#endif
if( p_vcd->b_end_of_track ) if( b_eot )
{ {
input_area_t *p_area;
/* EOF ? */
if( p_vcd->i_track >= p_vcd->nb_tracks - 1 )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0;
}
intf_WarnMsg( 4, "vcd info: new title" ); intf_WarnMsg( 4, "vcd info: new title" );
p_vcd->b_end_of_track = 0;
VCDSetArea( p_input, p_input->stream.pp_areas[ p_area = p_input->stream.pp_areas[
p_input->stream.p_selected_area->i_id + 1] ); p_input->stream.p_selected_area->i_id + 1 ];
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0; p_area->i_part = 1;
VCDSetArea( p_input, p_area );
} }
vlc_mutex_unlock( &p_input->stream.stream_lock );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0; return( i_packet + 1 );
} }
/***************************************************************************** /*****************************************************************************
...@@ -665,7 +602,6 @@ static int VCDRewind( input_thread_t * p_input ) ...@@ -665,7 +602,6 @@ static int VCDRewind( input_thread_t * p_input )
return( -1 ); return( -1 );
} }
/**************************************************************************** /****************************************************************************
* VCDSeek * VCDSeek
****************************************************************************/ ****************************************************************************/
...@@ -675,368 +611,11 @@ static void VCDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -675,368 +611,11 @@ static void VCDSeek( input_thread_t * p_input, off_t i_off )
p_vcd = (thread_vcd_data_t *) p_input->p_plugin_data; p_vcd = (thread_vcd_data_t *) p_input->p_plugin_data;
p_vcd->current_sector = p_vcd->tracks_sector[p_vcd->current_track] p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track]
+ i_off; + i_off / (off_t)VCD_DATA_SIZE;
p_input->stream.p_selected_area->i_tell = p_vcd->current_sector p_input->stream.p_selected_area->i_tell =
- p_input->stream.p_selected_area->i_start; (off_t)p_vcd->i_sector * (off_t)VCD_DATA_SIZE
- p_input->stream.p_selected_area->i_start;
return ;
} }
/*
* Packet management utilities
*/
/*****************************************************************************
* NewPacket: allocates a data packet
*****************************************************************************/
static struct data_packet_s * NewPacket( void * p_packet_cache,
size_t l_size )
{
packet_cache_t * p_cache;
data_packet_t * p_data;
long l_index;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "PPacket cache not initialized" );
return NULL;
}
#endif
/* Safety check */
if( l_size > INPUT_MAX_PACKET_SIZE )
{
intf_ErrMsg( "Packet too big (%d)", l_size );
return NULL;
}
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the data cache is empty */
if( p_cache->data.l_index == 0 )
{
/* Allocates a new packet */
p_data = malloc( sizeof(data_packet_t) );
if( p_data == NULL )
{
intf_ErrMsg( "Out of memory" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: data packet allocated" );
#endif
}
else
{
/* Takes the packet out from the cache */
if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ])
== NULL )
{
intf_ErrMsg( "NULL packet in the data cache" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
}
if( l_size < MAX_SMALL_SIZE )
{
/* Small buffer */
/* Checks whether the buffer cache is empty */
if( p_cache->smallbuffer.l_index == 0 )
{
/* Allocates a new packet */
p_data->p_buffer = malloc( l_size );
if( p_data->p_buffer == NULL )
{
intf_DbgMsg( "Out of memory" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: small buffer allocated" );
#endif
p_data->l_size = l_size;
}
else
{
/* Takes the packet out from the cache */
l_index = -- p_cache->smallbuffer.l_index;
if( (p_data->p_buffer = p_cache->smallbuffer.p_stack[l_index].p_data)
== NULL )
{
intf_ErrMsg( "NULL packet in the small buffer cache" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
/* Reallocates the packet if it is too small or too large */
if( p_cache->smallbuffer.p_stack[l_index].l_size < l_size ||
p_cache->smallbuffer.p_stack[l_index].l_size > 2*l_size )
{
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
p_data->l_size = l_size;
}
else
{
p_data->l_size = p_cache->smallbuffer.p_stack[l_index].l_size;
}
}
}
else
{
/* Large buffer */
/* Checks whether the buffer cache is empty */
if( p_cache->largebuffer.l_index == 0 )
{
/* Allocates a new packet */
p_data->p_buffer = malloc( l_size );
if ( p_data->p_buffer == NULL )
{
intf_ErrMsg( "Out of memory" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: large buffer allocated" );
#endif
p_data->l_size = l_size;
}
else
{
/* Takes the packet out from the cache */
l_index = -- p_cache->largebuffer.l_index;
p_data->p_buffer = p_cache->largebuffer.p_stack[l_index].p_data;
if( p_data->p_buffer == NULL )
{
intf_ErrMsg( "NULL packet in the small buffer cache" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
/* Reallocates the packet if it is too small or too large */
if( p_cache->largebuffer.p_stack[l_index].l_size < l_size ||
p_cache->largebuffer.p_stack[l_index].l_size > 2*l_size )
{
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
p_data->l_size = l_size;
}
else
{
p_data->l_size = p_cache->largebuffer.p_stack[l_index].l_size;
}
}
}
vlc_mutex_unlock( &p_cache->lock );
/* Initialize data */
p_data->p_next = NULL;
p_data->b_discard_payload = 0;
p_data->p_payload_start = p_data->p_buffer;
p_data->p_payload_end = p_data->p_buffer + l_size;
return( p_data );
}
/*****************************************************************************
* NewPES: allocates a pes packet
*****************************************************************************/
static pes_packet_t * NewPES( void * p_packet_cache )
{
packet_cache_t * p_cache;
pes_packet_t * p_pes;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return NULL;
}
#endif
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the PES cache is empty */
if( p_cache->pes.l_index == 0 )
{
/* Allocates a new packet */
p_pes = malloc( sizeof(pes_packet_t) );
if( p_pes == NULL )
{
intf_DbgMsg( "Out of memory" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: PES packet allocated" );
#endif
}
else
{
/* Takes the packet out from the cache */
p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ];
if( p_pes == NULL )
{
intf_ErrMsg( "NULL packet in the data cache" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
}
vlc_mutex_unlock( &p_cache->lock );
p_pes->b_data_alignment = p_pes->b_discontinuity =
p_pes->i_pts = p_pes->i_dts = 0;
p_pes->i_pes_size = 0;
p_pes->p_first = NULL;
return( p_pes );
}
/*****************************************************************************
* DeletePacket: deletes a data packet
*****************************************************************************/
static void DeletePacket( void * p_packet_cache,
data_packet_t * p_data )
{
packet_cache_t * p_cache;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return;
}
#endif
ASSERT( p_data );
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the data cache is full */
if ( p_cache->data.l_index < DATA_CACHE_SIZE )
{
/* Cache not full: store the packet in it */
p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
/* Small buffer or large buffer? */
if ( p_data->l_size < MAX_SMALL_SIZE )
{
/* Checks whether the small buffer cache is full */
if ( p_cache->smallbuffer.l_index < SMALL_CACHE_SIZE )
{
p_cache->smallbuffer.p_stack[
p_cache->smallbuffer.l_index ].l_size = p_data->l_size;
p_cache->smallbuffer.p_stack[
p_cache->smallbuffer.l_index++ ].p_data = p_data->p_buffer;
}
else
{
ASSERT( p_data->p_buffer );
free( p_data->p_buffer );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: small buffer freed" );
#endif
}
}
else
{
/* Checks whether the large buffer cache is full */
if ( p_cache->largebuffer.l_index < LARGE_CACHE_SIZE )
{
p_cache->largebuffer.p_stack[
p_cache->largebuffer.l_index ].l_size = p_data->l_size;
p_cache->largebuffer.p_stack[
p_cache->largebuffer.l_index++ ].p_data = p_data->p_buffer;
}
else
{
ASSERT( p_data->p_buffer );
free( p_data->p_buffer );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: large buffer freed" );
#endif
}
}
}
else
{
/* Cache full: the packet must be freed */
free( p_data->p_buffer );
free( p_data );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: data packet freed" );
#endif
}
vlc_mutex_unlock( &p_cache->lock );
}
/*****************************************************************************
* DeletePES: deletes a PES packet and associated data packets
*****************************************************************************/
static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
{
packet_cache_t * p_cache;
data_packet_t * p_data;
data_packet_t * p_next;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return;
}
#endif
ASSERT( p_pes);
p_data = p_pes->p_first;
while( p_data != NULL )
{
p_next = p_data->p_next;
DeletePacket( p_cache, p_data );
p_data = p_next;
}
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the PES cache is full */
if ( p_cache->pes.l_index < PES_CACHE_SIZE )
{
/* Cache not full: store the packet in it */
p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
}
else
{
/* Cache full: the packet must be freed */
free( p_pes );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: PES packet freed" );
#endif
}
vlc_mutex_unlock( &p_cache->lock );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_vcd.h: thread structure of the VCD plugin * input_vcd.h: thread structure of the VCD plugin
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: input_vcd.h,v 1.1 2001/10/23 03:17:49 jobi Exp $ * $Id: input_vcd.h,v 1.1.2.1 2001/12/31 01:21:45 massiot Exp $
* *
* Author: Johan Bilien <jobi@via.ecp.fr> * Author: Johan Bilien <jobi@via.ecp.fr>
* *
...@@ -21,25 +21,17 @@ ...@@ -21,25 +21,17 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
/***************************************************************************** /*****************************************************************************
* thread_vcd_data_t: VCD information * thread_vcd_data_t: VCD information
*****************************************************************************/ *****************************************************************************/
typedef struct thread_vcd_data_s typedef struct thread_vcd_data_s
{ {
int vcdhandle; // File descriptor int i_handle; /* File descriptor */
int nb_tracks; // Nb of tracks (titles) int nb_tracks; /* Nb of tracks (titles) */
int current_track; // Current track int i_track; /* Current track */
int current_sector; // Current Sector int i_sector; /* Current Sector */
int * tracks_sector; // index of tracks int * p_sectors; /* Track sectors */
boolean_t b_end_of_track; // if the end of track is boolean_t b_end_of_track; /* If the end of track was reached */
// reached
} thread_vcd_data_t ;
} thread_vcd_data_t;
...@@ -71,129 +71,97 @@ ...@@ -71,129 +71,97 @@
#include "modules.h" #include "modules.h"
#include "modules_export.h" #include "modules_export.h"
#include "input_vcd.h"
#include "linux_cdrom_tools.h" #include "linux_cdrom_tools.h"
/***************************************************************************** /*****************************************************************************
* read_toc : Reads the Table of Content of a CD-ROM and fills p_vcd with * * ioctl_ReadTocHeader: Read the TOC header and return the track number.
* the read information * *****************************************************************************/
*****************************************************************************/ int ioctl_GetTrackCount( int i_fd )
int read_toc ( thread_vcd_data_t * p_vcd ) {
{ struct cdrom_tochdr tochdr;
int i ;
struct cdrom_tochdr tochdr ; /* First we read the TOC header */
struct cdrom_tocentry tocent ; if( ioctl( i_fd, CDROMREADTOCHDR, &tochdr ) == -1 )
int fd = p_vcd->vcdhandle ;
/* first we read the TOC header */
if (ioctl(fd, CDROMREADTOCHDR, &tochdr) == -1)
{ {
intf_ErrMsg("problem occured when reading CD's TOCHDR\n") ; intf_ErrMsg( "vcd error: could not read TOCHDR" );
return -1 ; return -1;
} }
p_vcd->nb_tracks = tochdr.cdth_trk1; return tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
/* nb_tracks + 1 because we put the lead_out tracks for computing last }
track's size */
p_vcd->tracks_sector = malloc( ( p_vcd->nb_tracks + 1 ) /*****************************************************************************
* sizeof( int ) ); * ioctl_GetSectors: Read the Table of Contents and fill p_vcd.
if ( p_vcd->tracks_sector == NULL ) *****************************************************************************/
int * ioctl_GetSectors( int i_fd )
{
int i, i_tracks;
int *p_sectors;
struct cdrom_tochdr tochdr;
struct cdrom_tocentry tocent;
/* First we read the TOC header */
if( ioctl( i_fd, CDROMREADTOCHDR, &tochdr ) == -1 )
{ {
intf_ErrMsg("could not malloc tracks_sector"); intf_ErrMsg( "vcd error: could not read TOCHDR" );
return -1; return NULL;
} }
/* then for each track we read its TOC entry */ i_tracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
for( i=tochdr.cdth_trk0 ; i <= tochdr.cdth_trk1 ; i++ ) p_sectors = malloc( (i_tracks + 1) * sizeof(int) );
if( p_sectors == NULL )
{
intf_ErrMsg( "vcd error: could not allocate p_sectors" );
return NULL;
}
/* Fill the p_sectors structure with the track/sector matches */
for( i = 0 ; i <= i_tracks ; i++ )
{ {
tocent.cdte_track = i;
tocent.cdte_format = CDROM_LBA; tocent.cdte_format = CDROM_LBA;
if (ioctl( fd, CDROMREADTOCENTRY, &tocent) == -1 ) tocent.cdte_track =
( i == i_tracks ) ? CDROM_LEADOUT : tochdr.cdth_trk0 + i;
if( ioctl( i_fd, CDROMREADTOCENTRY, &tocent ) == -1 )
{ {
intf_ErrMsg( "problem occured when reading CD's TOCENTRY\n" ); intf_ErrMsg( "vcd error: could not read TOCENTRY" );
free ( p_vcd->tracks_sector ); free( p_sectors );
return -1; return NULL;
} }
p_vcd->tracks_sector[i-1] = tocent.cdte_addr.lba ;
p_sectors[ i ] = tocent.cdte_addr.lba;
} }
/* finally we read the lead-out track toc entry */
tocent.cdte_track = CDROM_LEADOUT ;
tocent.cdte_format = CDROM_LBA ;
if (ioctl(fd, CDROMREADTOCENTRY, &tocent) == -1)
{
intf_ErrMsg("problem occured when readind CD's
lead-out track TOC entry") ;
free (p_vcd->tracks_sector) ;
return -1 ;
}
p_vcd->tracks_sector[p_vcd->nb_tracks] = tocent.cdte_addr.lba ;
return 1 ;
return p_sectors;
} }
/**************************************************************************** /****************************************************************************
* VCD_sector_read : Function that reads a sector (2324 bytes) from VCD * ioctl_ReadSector: Read a sector (2324 bytes)
****************************************************************************/ ****************************************************************************/
int VCD_sector_read ( struct thread_vcd_data_s * p_vcd, byte_t * p_buffer ) int ioctl_ReadSector( int i_fd, int i_sector, byte_t * p_buffer )
{ {
byte_t p_read_block[VCD_SECTOR_SIZE] ; byte_t p_block[ VCD_SECTOR_SIZE ];
struct cdrom_msf0 msf_cursor ; int i_dummy = i_sector + 2 * CD_FRAMES;
msf_cursor = lba2msf( p_vcd->current_sector ) ; #define p_msf ((struct cdrom_msf0 *)p_block)
p_msf->minute = i_dummy / (CD_FRAMES * CD_SECS);
#ifdef DEBUG p_msf->second = ( i_dummy % (CD_FRAMES * CD_SECS) ) / CD_FRAMES;
intf_DbgMsg("Playing frame %d:%d-%d\n", msf_cursor.minute, p_msf->frame = ( i_dummy % (CD_FRAMES * CD_SECS) ) % CD_FRAMES;
msf_cursor.second, msf_cursor.frame) ;
#endif intf_DbgMsg( "vcd debug: playing frame %d:%d-%d",
p_msf->minute, p_msf->second, p_msf->frame);
memcpy(p_read_block, &msf_cursor, sizeof(struct cdrom_msf0)) ; #undef p_msf
if (ioctl(p_vcd->vcdhandle, CDROMREADRAW, p_read_block) == -1) if( ioctl(i_fd, CDROMREADRAW, p_block) == -1 )
{
intf_ErrMsg("problem occured when reading CD") ;
free (p_read_block) ;
return -1 ;
}
/* we don't want to keep the header of the read sector */
memcpy( p_buffer, &p_read_block[VCD_DATA_START],
VCD_DATA_SIZE );
p_vcd->current_sector ++;
if ( p_vcd->current_sector ==
p_vcd->tracks_sector[p_vcd->current_track + 1] )
{ {
p_vcd->b_end_of_track = 1; intf_ErrMsg( "vcd error: could not read block %i from disc",
i_sector );
return -1;
} }
return 1;
}
/* We don't want to keep the header of the read sector */
p_main->fast_memcpy( p_buffer, p_block + VCD_DATA_START, VCD_DATA_SIZE );
/***************************************************************************** return 0;
* lba2msf : converts a logical block address into a minute/second/frame
* address.
*****************************************************************************/
struct cdrom_msf0 lba2msf( int lba)
{
struct cdrom_msf0 msf_result ;
/* we add 2*CD_FRAMES since the 2 first seconds are not played*/
msf_result.minute = (lba+2*CD_FRAMES) / ( CD_FRAMES * CD_SECS ) ;
msf_result.second = ( (lba+2*CD_FRAMES) % ( CD_FRAMES * CD_SECS ) )
/ CD_FRAMES ;
msf_result.frame = ( (lba+2*CD_FRAMES) % ( CD_FRAMES * CD_SECS ) )
% CD_FRAMES ;
return msf_result ;
} }
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
/****************************************************************************** /******************************************************************************
* Prototypes * * Prototypes *
******************************************************************************/ ******************************************************************************/
int ioctl_GetTrackCount ( int );
int read_toc ( struct thread_vcd_data_s *); int * ioctl_GetSectors ( int );
int VCD_sector_read ( struct thread_vcd_data_s *, byte_t *) ; int ioctl_ReadSector ( int, int, byte_t * );
struct cdrom_msf0 lba2msf ( int ) ;
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* decoders. * decoders.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input.c,v 1.163.2.2 2001/12/12 02:13:20 sam Exp $ * $Id: input.c,v 1.163.2.3 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -120,9 +120,6 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) ...@@ -120,9 +120,6 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
return( NULL ); return( NULL );
} }
/* Packets read once */
p_input->i_read_once = INPUT_READ_ONCE;
/* Initialize thread properties */ /* Initialize thread properties */
p_input->b_die = 0; p_input->b_die = 0;
p_input->b_error = 0; p_input->b_error = 0;
...@@ -206,7 +203,7 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status ) ...@@ -206,7 +203,7 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
/* Request thread destruction */ /* Request thread destruction */
p_input->b_die = 1; p_input->b_die = 1;
/* Make the thread exit of an eventual vlc_cond_wait() */ /* Make the thread exit from an eventual vlc_cond_wait() */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
vlc_cond_signal( &p_input->stream.stream_wait ); vlc_cond_signal( &p_input->stream.stream_wait );
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
...@@ -229,9 +226,6 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status ) ...@@ -229,9 +226,6 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
*****************************************************************************/ *****************************************************************************/
static void RunThread( input_thread_t *p_input ) static void RunThread( input_thread_t *p_input )
{ {
int i_error, i;
data_packet_t ** pp_packets;
if( InitThread( p_input ) ) if( InitThread( p_input ) )
{ {
/* If we failed, wait before we are killed, and exit */ /* If we failed, wait before we are killed, and exit */
...@@ -242,22 +236,16 @@ static void RunThread( input_thread_t *p_input ) ...@@ -242,22 +236,16 @@ static void RunThread( input_thread_t *p_input )
return; return;
} }
/* initialization is completed */ /* initialization is complete */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_changed = 1; p_input->stream.b_changed = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
pp_packets = (data_packet_t **) malloc( p_input->i_read_once *
sizeof( data_packet_t * ) );
if( pp_packets == NULL )
{
intf_ErrMsg( "input error: out of memory" );
free( pp_packets );
p_input->b_error = 1;
}
while( !p_input->b_die && !p_input->b_error && !p_input->b_eof ) while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
{ {
data_packet_t * p_data;
int i_count, i;
p_input->c_loops++; p_input->c_loops++;
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -357,33 +345,33 @@ static void RunThread( input_thread_t *p_input ) ...@@ -357,33 +345,33 @@ static void RunThread( input_thread_t *p_input )
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
i_error = p_input->pf_read( p_input, pp_packets ); i_count = p_input->pf_read( p_input, &p_data );
/* Demultiplex read packets. */ /* Demultiplex read packets. */
for( i = 0; i < p_input->i_read_once && pp_packets[i] != NULL; i++ ) while( p_data != NULL )
{ {
data_packet_t * p_next = p_data->p_next;
p_data->p_next = NULL;
p_input->stream.c_packets_read++; p_input->stream.c_packets_read++;
p_input->pf_demux( p_input, pp_packets[i] ); p_input->pf_demux( p_input, p_data );
p_data = p_next;
} }
if( i_error ) if( i_count == 0 && p_input->stream.b_seekable )
{ {
if( i_error == 1 ) /* End of file - we do not set b_die because only the
{ * interface is allowed to do so. */
/* End of file - we do not set b_die because only the intf_WarnMsg( 3, "input: EOF reached" );
* interface is allowed to do so. */ p_input->b_eof = 1;
intf_WarnMsg( 3, "input: EOF reached" ); }
p_input->b_eof = 1; else if( i_count < 0 )
} {
else p_input->b_error = 1;
{
p_input->b_error = 1;
}
} }
} }
free( pp_packets );
if( p_input->b_error || p_input->b_eof ) if( p_input->b_error || p_input->b_eof )
{ {
ErrorThread( p_input ); ErrorThread( p_input );
...@@ -401,7 +389,6 @@ static void RunThread( input_thread_t *p_input ) ...@@ -401,7 +389,6 @@ static void RunThread( input_thread_t *p_input )
*****************************************************************************/ *****************************************************************************/
static int InitThread( input_thread_t * p_input ) static int InitThread( input_thread_t * p_input )
{ {
/* Initialize statistics */ /* Initialize statistics */
p_input->c_loops = 0; p_input->c_loops = 0;
p_input->stream.c_packets_read = 0; p_input->stream.c_packets_read = 0;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_dec.c: Functions for the management of decoders * input_dec.c: Functions for the management of decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: input_dec.c,v 1.19 2001/12/03 16:18:37 sam Exp $ * $Id: input_dec.c,v 1.19.2.1 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -144,21 +144,13 @@ void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes ) ...@@ -144,21 +144,13 @@ void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
{ {
vlc_mutex_lock( &p_decoder_fifo->data_lock ); vlc_mutex_lock( &p_decoder_fifo->data_lock );
if( !DECODER_FIFO_ISFULL( *p_decoder_fifo ) ) p_pes->p_next = NULL;
{ *p_decoder_fifo->pp_last = p_pes;
p_decoder_fifo->buffer[p_decoder_fifo->i_end] = p_pes; p_decoder_fifo->pp_last = &p_pes->p_next;
DECODER_FIFO_INCEND( *p_decoder_fifo ); p_decoder_fifo->i_depth++;
/* Warn the decoder that it's got work to do. */ /* Warn the decoder that it's got work to do. */
vlc_cond_signal( &p_decoder_fifo->data_wait ); vlc_cond_signal( &p_decoder_fifo->data_wait );
}
else
{
/* The FIFO is full !!! This should not happen. */
p_decoder_fifo->pf_delete_pes( p_decoder_fifo->p_packets_mgt,
p_pes );
intf_ErrMsg( "PES trashed - decoder fifo full !" );
}
vlc_mutex_unlock( &p_decoder_fifo->data_lock ); vlc_mutex_unlock( &p_decoder_fifo->data_lock );
} }
...@@ -261,7 +253,9 @@ static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input, ...@@ -261,7 +253,9 @@ static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input,
p_config->i_type = p_es->i_type; p_config->i_type = p_es->i_type;
p_config->p_stream_ctrl = &p_input->stream.control; p_config->p_stream_ctrl = &p_input->stream.control;
p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0; p_config->p_decoder_fifo->p_first = NULL;
p_config->p_decoder_fifo->pp_last = &p_config->p_decoder_fifo->p_first;
p_config->p_decoder_fifo->i_depth = 0;
p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0; p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data; p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes; p_config->p_decoder_fifo->pf_delete_pes = p_input->pf_delete_pes;
...@@ -274,14 +268,13 @@ static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input, ...@@ -274,14 +268,13 @@ static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input,
*****************************************************************************/ *****************************************************************************/
static void DeleteDecoderConfig( decoder_config_t * p_config ) static void DeleteDecoderConfig( decoder_config_t * p_config )
{ {
intf_StatMsg( "input stats: killing decoder for 0x%x, type 0x%x, %d PES in FIFO",
p_config->i_id, p_config->i_type,
p_config->p_decoder_fifo->i_depth );
/* Free all packets still in the decoder fifo. */ /* Free all packets still in the decoder fifo. */
while( !DECODER_FIFO_ISEMPTY( *p_config->p_decoder_fifo ) ) p_config->p_decoder_fifo->pf_delete_pes(
{ p_config->p_decoder_fifo->p_packets_mgt,
p_config->p_decoder_fifo->pf_delete_pes( p_config->p_decoder_fifo->p_first );
p_config->p_decoder_fifo->p_packets_mgt,
DECODER_FIFO_START( *p_config->p_decoder_fifo ) );
DECODER_FIFO_INCSTART( *p_config->p_decoder_fifo );
}
/* Destroy the lock and cond */ /* Destroy the lock and cond */
vlc_cond_destroy( &p_config->p_decoder_fifo->data_wait ); vlc_cond_destroy( &p_config->p_decoder_fifo->data_wait );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ext-dec.c: services to the decoders * input_ext-dec.c: services to the decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_ext-dec.c,v 1.21.2.1 2001/12/30 06:06:00 sam Exp $ * $Id: input_ext-dec.c,v 1.21.2.2 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -55,7 +55,7 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo, ...@@ -55,7 +55,7 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
/* Get the first data packet. */ /* Get the first data packet. */
vlc_mutex_lock( &p_fifo->data_lock ); vlc_mutex_lock( &p_fifo->data_lock );
while ( DECODER_FIFO_ISEMPTY( *p_fifo ) ) while ( p_fifo->p_first == NULL )
{ {
if ( p_fifo->b_die ) if ( p_fifo->b_die )
{ {
...@@ -64,7 +64,7 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo, ...@@ -64,7 +64,7 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
} }
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock ); 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_data = p_fifo->p_first->p_first;
p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start; 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->p_end = p_bit_stream->p_data->p_payload_end;
p_bit_stream->fifo.buffer = 0; p_bit_stream->fifo.buffer = 0;
...@@ -100,12 +100,7 @@ void DecoderError( decoder_fifo_t * p_fifo ) ...@@ -100,12 +100,7 @@ void DecoderError( decoder_fifo_t * p_fifo )
while( !p_fifo->b_die ) while( !p_fifo->b_die )
{ {
/* Trash all received PES packets */ /* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY(*p_fifo) ) p_fifo->pf_delete_pes( p_fifo->p_packets_mgt, p_fifo->p_first );
{
p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_fifo) );
DECODER_FIFO_INCSTART( *p_fifo );
}
/* Waiting for the input thread to put new PES packets in the fifo */ /* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock ); vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
...@@ -131,24 +126,29 @@ void NextDataPacket( bit_stream_t * p_bit_stream ) ...@@ -131,24 +126,29 @@ void NextDataPacket( bit_stream_t * p_bit_stream )
* time to jump to the next PES packet */ * time to jump to the next PES packet */
if( p_bit_stream->p_data->p_next == NULL ) if( p_bit_stream->p_data->p_next == NULL )
{ {
/* We are going to read/write the start and end indexes of the pes_packet_t * p_next;
* 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 ); vlc_mutex_lock( &p_fifo->data_lock );
/* Free the previous PES packet. */ /* Free the previous PES packet. */
p_next = p_fifo->p_first->p_next;
p_fifo->p_first->p_next = NULL;
p_fifo->pf_delete_pes( p_fifo->p_packets_mgt, p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
DECODER_FIFO_START( *p_fifo ) ); p_fifo->p_first );
DECODER_FIFO_INCSTART( *p_fifo ); p_fifo->p_first = p_next;
p_fifo->i_depth--;
if( DECODER_FIFO_ISEMPTY( *p_fifo ) ) if( p_fifo->p_first == NULL )
{ {
/* No PES in the FIFO. p_last is no longer valid. */
p_fifo->pp_last = &p_fifo->p_first;
/* Wait for the input to tell us when we receive a packet. */ /* Wait for the input to tell us when we receive a packet. */
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock ); vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
} }
/* The next byte could be found in the next PES packet */ /* The next byte could be found in the next PES packet */
p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first; p_bit_stream->p_data = p_fifo->p_first->p_first;
vlc_mutex_unlock( &p_fifo->data_lock ); vlc_mutex_unlock( &p_fifo->data_lock );
......
/*****************************************************************************
* dvd_netlist.c: netlist management v2
*****************************************************************************
* There is only one major change from input_netlist.c (1) : data is now a
* pointer to an offset in iovec ; and iovec has a reference counter. It
* will only be given back to netlist when refcount is zero.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input_netlist.c,v 1.47 2001/12/03 17:34:08 stef Exp $
*
* Authors: Henri Fallon <henri@videolan.org>
* Stphane Borel <stef@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <stdlib.h>
#include <string.h> /* memcpy(), memset() */
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#if defined( WIN32 )
# include <io.h> /* read() */
#else
# include <sys/uio.h> /* struct iovec */
#endif
#include "config.h"
#include "common.h"
#include "intf_msg.h" /* intf_*Msg */
#include "threads.h" /* mutex */
#include "mtime.h"
#if defined( WIN32 )
# include "input_iovec.h"
#endif
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
#include "input_ext-plugins.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/*****************************************************************************
* input_NetlistInit: allocates netlist buffers and init indexes
* ---
* Changes from input_NetList: we have to give the length of the buffer which
* is different from i_nb_data now, since we may have several data pointers
* in one iovec. Thus we can only delete an iovec when its refcount is 0.
* We only received a buffer with a GetIovec whereas NewPacket gives a pointer.
*****************************************************************************/
int input_NetlistInit( input_thread_t * p_input,
int i_nb_iovec, int i_nb_data, int i_nb_pes,
size_t i_buffer_size, int i_read_once )
{
unsigned int i_loop;
netlist_t * p_netlist;
/* First we allocate and initialise our netlist struct */
p_input->p_method_data = malloc(sizeof(netlist_t));
if ( p_input->p_method_data == NULL )
{
intf_ErrMsg("Unable to malloc the netlist struct");
return (-1);
}
p_netlist = (netlist_t *) p_input->p_method_data;
/* Nb of packets read once by input */
p_netlist->i_read_once = i_read_once;
/* In order to optimize netlist, we are taking i_nb_data a 2^i
* so that modulo is an "&".
* This is not changing i_nb data outside this function except in
* the netlist_t struct */
/* As i_loop is unsigned int, and i_ns_data int, this shouldn't be a
* problem */
for( i_loop = 1; i_loop < i_nb_data; i_loop *= 2 )
{
;
}
intf_DbgMsg( "Netlist : Required %i byte, got %u",i_nb_data,i_loop );
i_nb_data = i_loop;
/* Same thing for i_nb_pes */
for( i_loop = 1; i_loop < i_nb_pes; i_loop *= 2 )
{
;
}
intf_DbgMsg( "Netlist : Required %i byte, got %u",i_nb_pes,i_loop );
i_nb_pes = i_loop;
/* Same thing for i_nb_iovec */
for( i_loop = 1; i_loop < i_nb_iovec; i_loop *= 2 )
{
;
}
intf_DbgMsg( "Netlist : Required %i byte, got %u",i_nb_iovec,i_loop );
i_nb_iovec = i_loop;
/* allocate the buffers */
p_netlist->p_buffers = malloc( i_nb_iovec *i_buffer_size );
if ( p_netlist->p_buffers == NULL )
{
intf_ErrMsg ("Unable to malloc in netlist initialization (1)");
free( p_netlist );
return -1;
}
/* table of pointers to data packets */
p_netlist->p_data = malloc( i_nb_data *sizeof(data_packet_t) );
if ( p_netlist->p_data == NULL )
{
intf_ErrMsg ("Unable to malloc in netlist initialization (2)");
free( p_netlist->p_buffers );
free( p_netlist );
return -1;
}
/* table of pointer to PES packets */
p_netlist->p_pes = malloc( i_nb_pes *sizeof(pes_packet_t) );
if ( p_netlist->p_pes == NULL )
{
intf_ErrMsg ("Unable to malloc in netlist initialization (3)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist );
return -1;
}
/* allocate the FIFOs : tables of free pointers */
p_netlist->pp_free_data =
malloc( i_nb_data *sizeof(data_packet_t *) );
if ( p_netlist->pp_free_data == NULL )
{
intf_ErrMsg ("Unable to malloc in netlist initialization (4)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist );
return -1;
}
p_netlist->pp_free_pes =
malloc( i_nb_pes *sizeof(pes_packet_t *) );
if ( p_netlist->pp_free_pes == NULL )
{
intf_ErrMsg ("Unable to malloc in netlist initialization (5)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist->pp_free_data );
free( p_netlist );
return -1;
}
p_netlist->p_free_iovec =
malloc( (i_nb_iovec + p_netlist->i_read_once) * sizeof(struct iovec) );
if ( p_netlist->p_free_iovec == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (6)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist->pp_free_data );
free( p_netlist->pp_free_pes );
free( p_netlist );
return -1;
}
/* table for reference counter of iovecs */
p_netlist->pi_refcount = malloc( i_nb_iovec *sizeof(int) );
if ( p_netlist->pi_refcount == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (7)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist->pp_free_data );
free( p_netlist->pp_free_pes );
free( p_netlist->p_free_iovec );
free( p_netlist );
return -1;
}
/* Fill the data FIFO */
for ( i_loop = 0; i_loop < i_nb_data; i_loop++ )
{
p_netlist->pp_free_data[i_loop] =
p_netlist->p_data + i_loop;
/* by default, one data packet for one buffer */
if( i_nb_data == i_nb_iovec )
{
p_netlist->pp_free_data[i_loop]->p_buffer =
p_netlist->p_buffers + i_loop * i_buffer_size;
p_netlist->pp_free_data[i_loop]->p_payload_start =
p_netlist->pp_free_data[i_loop]->p_buffer;
p_netlist->pp_free_data[i_loop]->p_payload_end =
p_netlist->pp_free_data[i_loop]->p_buffer + i_buffer_size;
}
}
/* Fill the PES FIFO */
for ( i_loop = 0; i_loop < i_nb_pes ; i_loop++ )
{
p_netlist->pp_free_pes[i_loop] =
p_netlist->p_pes + i_loop;
}
/* Deal with the iovec */
for ( i_loop = 0; i_loop < i_nb_iovec; i_loop++ )
{
p_netlist->p_free_iovec[i_loop].iov_base =
p_netlist->p_buffers + i_loop * i_buffer_size;
p_netlist->p_free_iovec[i_loop].iov_len = i_buffer_size;
}
/* initialize reference counters */
memset( p_netlist->pi_refcount, 0, i_nb_iovec *sizeof(int) );
/* vlc_mutex_init */
vlc_mutex_init (&p_netlist->lock);
/* initialize indexes */
p_netlist->i_iovec_start = 0;
p_netlist->i_iovec_end = i_nb_iovec - 1;
p_netlist->i_data_start = 0;
p_netlist->i_data_end = i_nb_data - 1;
p_netlist->i_pes_start = 0;
p_netlist->i_pes_end = i_nb_pes - 1;
/* we give (nb - 1) to use & instead of %
* if you really need nb you have to add 1 */
p_netlist->i_nb_iovec = i_nb_iovec - 1;
p_netlist->i_nb_data = i_nb_data - 1;
p_netlist->i_nb_pes = i_nb_pes - 1;
p_netlist->i_buffer_size = i_buffer_size;
return 0; /* Everything went all right */
}
/*****************************************************************************
* input_NetlistGetiovec: returns an iovec pointer for a readv() operation
*****************************************************************************
* We return an iovec vector, so that readv can read many packets at a time.
* pp_data will be set to direct to the fifo pointer in DVDMviovec, which
* will allow us to get the corresponding data_packet.
*****************************************************************************/
struct iovec * input_NetlistGetiovec( void * p_method_data )
{
netlist_t * p_netlist;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* check that we have enough free iovec */
if( (
(p_netlist->i_iovec_end - p_netlist->i_iovec_start)
& p_netlist->i_nb_iovec ) < p_netlist->i_read_once )
{
intf_WarnMsg( 4, "input info: waiting for free iovec" );
msleep( INPUT_IDLE_SLEEP );
while( (
(p_netlist->i_iovec_end - p_netlist->i_iovec_start)
& p_netlist->i_nb_iovec ) < p_netlist->i_read_once )
{
msleep( INPUT_IDLE_SLEEP );
}
intf_WarnMsg( 4, "input info: found free iovec" );
}
if( (
(p_netlist->i_data_end - p_netlist->i_data_start)
& p_netlist->i_nb_data ) < p_netlist->i_read_once )
{
intf_WarnMsg( 4, "input info: waiting for free data packet" );
msleep( INPUT_IDLE_SLEEP );
while( (
(p_netlist->i_data_end - p_netlist->i_data_start)
& p_netlist->i_nb_data ) < p_netlist->i_read_once )
{
msleep( INPUT_IDLE_SLEEP );
}
intf_WarnMsg( 4, "input info: found free data packet" );
}
/* readv only takes contiguous buffers
* so, as a solution, we chose to have a FIFO a bit longer
* than i_nb_data, and copy the begining of the FIFO to its end
* if the readv needs to go after the end */
if( p_netlist->i_nb_iovec - p_netlist->i_iovec_start + 1 <
p_netlist->i_read_once )
{
memcpy( &p_netlist->p_free_iovec[p_netlist->i_nb_iovec + 1],
p_netlist->p_free_iovec,
(p_netlist->i_read_once -
(p_netlist->i_nb_iovec + 1 - p_netlist->i_iovec_start))
* sizeof(struct iovec)
);
}
return p_netlist->p_free_iovec + p_netlist->i_iovec_start;
}
/*****************************************************************************
* input_NetlistMviovec: move the iovec pointer by one after a readv()
* operation and gives a data_packet corresponding to iovec in p_data
*****************************************************************************/
void input_NetlistMviovec( void * p_method_data, int i_nb_iovec,
struct data_packet_s ** pp_data )
{
netlist_t * p_netlist;
unsigned int i_loop = 0;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock( &p_netlist->lock );
/* Fills a table of pointers to packets associated with the io_vec's */
while( i_loop < i_nb_iovec )
{
pp_data[i_loop] = p_netlist->pp_free_data[p_netlist->i_data_start];
pp_data[i_loop]->p_buffer =
p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
pp_data[i_loop]->p_payload_start = pp_data[i_loop]->p_buffer;
pp_data[i_loop]->p_payload_end =
pp_data[i_loop]->p_buffer + p_netlist->i_buffer_size;
pp_data[i_loop]->p_next = NULL;
pp_data[i_loop]->b_discard_payload = 0;
pp_data[i_loop]->pi_refcount = p_netlist->pi_refcount +
p_netlist->i_iovec_start;
if( (*pp_data[i_loop]->pi_refcount) != 0)
{
intf_ErrMsg( "netlist error: refcount should be 0 (%d)",
(*pp_data[i_loop]->pi_refcount) );
}
(*pp_data[i_loop]->pi_refcount) = 1;
p_netlist->i_iovec_start ++;
p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
p_netlist->i_data_start ++;
p_netlist->i_data_start &= p_netlist->i_nb_data;
i_loop ++;
}
/* unlock */
vlc_mutex_unlock( &p_netlist->lock );
}
/*****************************************************************************
* input_NetlistNewPtr: returns a free data_packet_t
* Gives a pointer ; its fields need to be initialized
*****************************************************************************/
struct data_packet_s * input_NetlistNewPtr( void * p_method_data )
{
netlist_t * p_netlist;
struct data_packet_s * p_return;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* check */
if ( p_netlist->i_data_start == p_netlist->i_data_end )
{
intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
return ( NULL );
}
p_return = (p_netlist->pp_free_data[p_netlist->i_data_start]);
p_netlist->i_data_start++;
p_netlist->i_data_start &= p_netlist->i_nb_data;
p_return->p_payload_start = p_return->p_buffer;
p_return->p_payload_end =
p_return->p_buffer + p_netlist->i_buffer_size;
p_return->p_next = NULL;
p_return->b_discard_payload = 0;
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
return ( p_return );
}
/*****************************************************************************
* input_NetlistNewPacket: returns a free data_packet_t, and takes
* a corresponding storage iovec.
*****************************************************************************/
struct data_packet_s * input_NetlistNewPacket( void * p_method_data,
size_t i_buffer_size )
{
netlist_t * p_netlist;
struct data_packet_s * p_packet;
/* cast */
p_netlist = (netlist_t *)p_method_data;
#ifdef DEBUG
if( i_buffer_size > p_netlist->i_buffer_size )
{
/* This should not happen */
intf_ErrMsg( "Netlist packet too small !" );
return NULL;
}
#endif
/* lock */
vlc_mutex_lock( &p_netlist->lock );
/* check */
if ( p_netlist->i_iovec_start == p_netlist->i_iovec_end )
{
intf_ErrMsg("Empty io_vec FIFO in netlist. Unable to allocate memory");
return ( NULL );
}
if ( p_netlist->i_data_start == p_netlist->i_data_end )
{
intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
return ( NULL );
}
/* Gives an io_vec and associated data */
p_packet = p_netlist->pp_free_data[p_netlist->i_data_start];
p_packet->p_buffer =
p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
p_packet->p_payload_start = p_packet->p_buffer;
p_packet->p_payload_end =
p_packet->p_buffer + i_buffer_size;
p_packet->p_next = NULL;
p_packet->b_discard_payload = 0;
p_packet->pi_refcount = p_netlist->pi_refcount + p_netlist->i_iovec_start;
if( (*p_packet->pi_refcount) != 0)
{
intf_ErrMsg( "netlist error: refcount should be 0 (%d)",
(*p_packet->pi_refcount) );
}
(*p_packet->pi_refcount) = 1;
p_netlist->i_iovec_start ++;
p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
p_netlist->i_data_start ++;
p_netlist->i_data_start &= p_netlist->i_nb_data;
/* unlock */
vlc_mutex_unlock( &p_netlist->lock );
return p_packet;
}
/*****************************************************************************
* input_NetlistNewPES: returns a free pes_packet_t
*****************************************************************************/
struct pes_packet_s * input_NetlistNewPES( void * p_method_data )
{
netlist_t * p_netlist;
pes_packet_t * p_return;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* check */
if ( p_netlist->i_pes_start == p_netlist->i_pes_end )
{
intf_ErrMsg("Empty PES FIFO in netlist - Unable to allocate memory");
return ( NULL );
}
/* allocate */
p_return = p_netlist->pp_free_pes[p_netlist->i_pes_start];
p_netlist->i_pes_start++;
p_netlist->i_pes_start &= p_netlist->i_nb_pes;
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
/* initialize PES */
p_return->b_data_alignment = 0;
p_return->b_discontinuity = 0;
p_return->i_pts = 0;
p_return->i_dts = 0;
p_return->i_pes_size = 0;
p_return->p_first = NULL;
return ( p_return );
}
/*****************************************************************************
* input_NetlistDeletePacket: puts a data_packet_t back into the netlist
*****************************************************************************/
void input_NetlistDeletePacket( void * p_method_data, data_packet_t * p_data )
{
netlist_t * p_netlist;
/* cast */
p_netlist = (netlist_t *) p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* Delete data_packet */
p_netlist->i_data_end ++;
p_netlist->i_data_end &= p_netlist->i_nb_data;
p_data->p_payload_start = p_data->p_buffer;
p_data->p_payload_end = p_data->p_buffer + p_netlist->i_buffer_size;
p_netlist->pp_free_data[p_netlist->i_data_end] = p_data;
p_data->p_next = NULL;
p_data->b_discard_payload = 0;
/* Update reference counter */
(*p_data->pi_refcount)--;
if( (*p_data->pi_refcount) == 0 )
{
(*p_data->pi_refcount) = 0;
p_netlist->i_iovec_end++;
p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
p_data->p_buffer;
}
else if( (*p_data->pi_refcount) < 0 )
{
intf_ErrMsg( "netlist error: refcount can't be negative (%d)",
(*p_data->pi_refcount) );
}
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
}
/*****************************************************************************
* input_NetlistDeletePES: puts a pes_packet_t back into the netlist
*****************************************************************************/
void input_NetlistDeletePES( void * p_method_data, pes_packet_t * p_pes )
{
netlist_t * p_netlist;
data_packet_t * p_current_packet;
data_packet_t * p_next_packet;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* delete free p_pes->p_first, p_next ... */
p_current_packet = p_pes->p_first;
while ( p_current_packet != NULL )
{
/* copy of NetListDeletePacket, duplicate code avoid many locks */
p_netlist->i_data_end ++;
p_netlist->i_data_end &= p_netlist->i_nb_data;
/* re initialize */
p_current_packet->p_payload_start = p_current_packet->p_buffer;
p_current_packet->p_payload_end = p_current_packet->p_buffer
+ p_netlist->i_buffer_size;
p_netlist->pp_free_data[p_netlist->i_data_end] = p_current_packet;
/* Update reference counter */
(*p_current_packet->pi_refcount)--;
if( (*p_current_packet->pi_refcount) == 0 )
{
(*p_current_packet->pi_refcount) = 0;
p_netlist->i_iovec_end++;
p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
p_current_packet->p_buffer;
}
else if( (*p_current_packet->pi_refcount) < 0 )
{
intf_ErrMsg( "netlist error: refcount can't be negative (%d)",
(*p_current_packet->pi_refcount) );
}
p_next_packet = p_current_packet->p_next;
p_current_packet->p_next = NULL;
p_current_packet->b_discard_payload = 0;
p_current_packet = p_next_packet;
}
/* delete our current PES packet */
p_netlist->i_pes_end ++;
p_netlist->i_pes_end &= p_netlist->i_nb_pes;
p_netlist->pp_free_pes[p_netlist->i_pes_end] = p_pes;
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
}
/*****************************************************************************
* input_NetlistEnd: frees all allocated structures
*****************************************************************************/
void input_NetlistEnd( input_thread_t * p_input )
{
netlist_t * p_netlist;
/* cast */
p_netlist = ( netlist_t * ) p_input->p_method_data;
/* destroy the mutex lock */
vlc_mutex_destroy( &p_netlist->lock );
/* free the FIFO, the buffer, and the netlist structure */
free( p_netlist->pi_refcount );
free( p_netlist->p_free_iovec );
free( p_netlist->pp_free_pes );
free( p_netlist->pp_free_data );
free( p_netlist->p_pes );
free( p_netlist->p_data );
free( p_netlist->p_buffers );
/* free the netlist */
free( p_netlist );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg_system.c: TS, PS and PES management * mpeg_system.c: TS, PS and PES management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: mpeg_system.c,v 1.69.2.4 2001/12/17 16:37:25 sam Exp $ * $Id: mpeg_system.c,v 1.69.2.5 2001/12/31 01:21:45 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr> * Michel Lespinasse <walken@via.ecp.fr>
...@@ -136,7 +136,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -136,7 +136,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
if( MoveChunk( p_header, &p_data, &p_byte, PES_HEADER_SIZE ) if( MoveChunk( p_header, &p_data, &p_byte, PES_HEADER_SIZE )
!= PES_HEADER_SIZE ) != PES_HEADER_SIZE )
{ {
intf_WarnMsg( 1, "PES packet too short to have a header" ); intf_WarnMsg( 1, "input: PES packet too short to have a header" );
p_input->pf_delete_pes( p_input->p_method_data, p_pes ); p_input->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL; p_pes = NULL;
return; return;
...@@ -154,7 +154,8 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -154,7 +154,8 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
if( (p_header[0] || p_header[1] || (p_header[2] != 1)) ) if( (p_header[0] || p_header[1] || (p_header[2] != 1)) )
{ {
/* packet_start_code_prefix != 0x000001 */ /* packet_start_code_prefix != 0x000001 */
intf_ErrMsg( "PES packet doesn't start with 0x000001 : data loss" ); intf_ErrMsg( "input error: data loss, "
"PES packet doesn't start with 0x000001" );
p_input->pf_delete_pes( p_input->p_method_data, p_pes ); p_input->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL; p_pes = NULL;
} }
...@@ -167,7 +168,8 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -167,7 +168,8 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
{ {
/* PES_packet_length is set and != total received payload */ /* PES_packet_length is set and != total received payload */
/* Warn the decoder that the data may be corrupt. */ /* Warn the decoder that the data may be corrupt. */
intf_WarnMsg( 1, "PES sizes do not match : packet corrupted" ); intf_WarnMsg( 1, "input: packet corrupted, "
"PES sizes do not match" );
} }
switch( p_es->i_stream_id ) switch( p_es->i_stream_id )
...@@ -273,7 +275,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -273,7 +275,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
} }
if( i_pes_header_size == 23 ) if( i_pes_header_size == 23 )
{ {
intf_ErrMsg( "Too much MPEG-1 stuffing" ); intf_ErrMsg( "input error: too much MPEG-1 stuffing" );
p_input->pf_delete_pes( p_input->p_method_data, p_pes ); p_input->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL; p_pes = NULL;
return; return;
...@@ -474,10 +476,11 @@ void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data, ...@@ -474,10 +476,11 @@ void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data,
else else
{ {
/* Update the relations between the data packets */ /* Update the relations between the data packets */
p_es->p_last->p_next = p_data; p_pes->p_last->p_next = p_data;
} }
p_es->p_last = p_data; p_pes->p_last = p_data;
p_pes->i_nb_data++;
/* Size of the payload carried in the data packet */ /* Size of the payload carried in the data packet */
p_pes->i_pes_size += (p_data->p_payload_end p_pes->i_pes_size += (p_data->p_payload_end
...@@ -505,13 +508,13 @@ static u16 GetID( data_packet_t * p_data ) ...@@ -505,13 +508,13 @@ static u16 GetID( data_packet_t * p_data )
{ {
u16 i_id; u16 i_id;
i_id = p_data->p_payload_start[3]; /* stream_id */ i_id = p_data->p_demux_start[3]; /* stream_id */
if( i_id == 0xBD ) if( i_id == 0xBD )
{ {
/* FIXME : this is not valid if the header is split in multiple /* FIXME : this is not valid if the header is split in multiple
* packets */ * packets */
/* stream_private_id */ /* stream_private_id */
i_id |= p_data->p_payload_start[ 9 + p_data->p_payload_start[8] ] << 8; i_id |= p_data->p_demux_start[ 9 + p_data->p_demux_start[8] ] << 8;
} }
return( i_id ); return( i_id );
} }
...@@ -530,14 +533,14 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -530,14 +533,14 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
int i; int i;
int i_new_es_number = 0; int i_new_es_number = 0;
if( p_data->p_payload_start + 10 > p_data->p_payload_end ) if( p_data->p_demux_start + 10 > p_data->p_payload_end )
{ {
intf_ErrMsg( "PSM too short : packet corrupt" ); intf_ErrMsg( "PSM too short : packet corrupt" );
return; return;
} }
if( p_demux->b_has_PSM if( p_demux->b_has_PSM
&& p_demux->i_PSM_version == (p_data->p_payload_start[6] & 0x1F) ) && p_demux->i_PSM_version == (p_data->p_demux_start[6] & 0x1F) )
{ {
/* Already got that one. */ /* Already got that one. */
return; return;
...@@ -545,12 +548,12 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -545,12 +548,12 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
intf_DbgMsg( "Building PSM" ); intf_DbgMsg( "Building PSM" );
p_demux->b_has_PSM = 1; p_demux->b_has_PSM = 1;
p_demux->i_PSM_version = p_data->p_payload_start[6] & 0x1F; p_demux->i_PSM_version = p_data->p_demux_start[6] & 0x1F;
/* Go to elementary_stream_map_length, jumping over /* Go to elementary_stream_map_length, jumping over
* program_stream_info. */ * program_stream_info. */
p_byte = p_data->p_payload_start + 10 p_byte = p_data->p_demux_start + 10
+ U16_AT(&p_data->p_payload_start[8]); + U16_AT(&p_data->p_demux_start[8]);
if( p_byte > p_data->p_payload_end ) if( p_byte > p_data->p_payload_end )
{ {
intf_ErrMsg( "PSM too short : packet corrupt" ); intf_ErrMsg( "PSM too short : packet corrupt" );
...@@ -655,7 +658,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -655,7 +658,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
u32 i_code; u32 i_code;
es_descriptor_t * p_es = NULL; es_descriptor_t * p_es = NULL;
i_code = p_data->p_payload_start[3]; i_code = p_data->p_demux_start[3];
if( i_code > 0xBC ) /* ES start code */ if( i_code > 0xBC ) /* ES start code */
{ {
...@@ -694,7 +697,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -694,7 +697,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
i_id, 0 ); i_id, 0 );
if( p_es != NULL ) if( p_es != NULL )
{ {
p_es->i_stream_id = p_data->p_payload_start[3]; p_es->i_stream_id = p_data->p_demux_start[3];
/* Set stream type and auto-spawn. */ /* Set stream type and auto-spawn. */
if( (i_id & 0xF0) == 0xE0 ) if( (i_id & 0xF0) == 0xE0 )
...@@ -794,7 +797,10 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -794,7 +797,10 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
boolean_t b_trash = 0; boolean_t b_trash = 0;
es_descriptor_t * p_es = NULL; es_descriptor_t * p_es = NULL;
i_code = U32_AT( p_data->p_payload_start ); i_code = ((u32)p_data->p_demux_start[0] << 24)
| ((u32)p_data->p_demux_start[1] << 16)
| ((u32)p_data->p_demux_start[2] << 8)
| p_data->p_demux_start[3];
if( i_code <= 0x1BC ) if( i_code <= 0x1BC )
{ {
switch( i_code ) switch( i_code )
...@@ -805,12 +811,12 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -805,12 +811,12 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
mtime_t scr_time; mtime_t scr_time;
u32 i_mux_rate; u32 i_mux_rate;
if( (p_data->p_payload_start[4] & 0xC0) == 0x40 ) if( (p_data->p_demux_start[4] & 0xC0) == 0x40 )
{ {
/* MPEG-2 */ /* MPEG-2 */
byte_t p_header[14]; byte_t p_header[14];
byte_t * p_byte; byte_t * p_byte;
p_byte = p_data->p_payload_start; p_byte = p_data->p_demux_start;
if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 ) if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 )
{ {
...@@ -841,7 +847,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -841,7 +847,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
/* MPEG-1 SCR is like PTS. */ /* MPEG-1 SCR is like PTS. */
byte_t p_header[12]; byte_t p_header[12];
byte_t * p_byte; byte_t * p_byte;
p_byte = p_data->p_payload_start; p_byte = p_data->p_demux_start;
if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 ) if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 )
{ {
...@@ -943,7 +949,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -943,7 +949,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
es_ts_data_t * p_es_demux = NULL; es_ts_data_t * p_es_demux = NULL;
pgrm_ts_data_t * p_pgrm_demux = NULL; pgrm_ts_data_t * p_pgrm_demux = NULL;
#define p (p_data->p_buffer) #define p (p_data->p_demux_start)
/* Extract flags values from TS common header. */ /* Extract flags values from TS common header. */
i_pid = ((p[1] & 0x1F) << 8) | p[2]; i_pid = ((p[1] & 0x1F) << 8) | p[2];
b_unit_start = (p[1] & 0x40); b_unit_start = (p[1] & 0x40);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment