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 \
# C Objects
#
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
AUDIO_OUTPUT := audio_output aout_ext-dec aout_u8 aout_s8 aout_u16 aout_s16 aout_spdif
MISC := mtime tests modules netutils iso_lang
......
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* 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>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -347,18 +347,6 @@ typedef struct module_symbols_s
struct pgrm_descriptor_s *,
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 )
( int, int, long, long, long, void * );
void ( * aout_DestroyFifo ) ( struct aout_fifo_s * );
......
......@@ -97,13 +97,6 @@
/* Environment variable containing the memcpy method */
#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
*/
......@@ -175,6 +168,9 @@
/* Maximum length of a hostname or source name */
#define INPUT_MAX_SOURCE_LENGTH 100
/* Maximum memory the input is allowed to use (20 MB) */
#define INPUT_MAX_ALLOCATION 20971520
/* Default network protocol */
#define INPUT_NETWORK_PROTOCOL_VAR "vlc_network_protocol"
#define INPUT_NETWORK_PROTOCOL_DEFAULT "ts"
......
......@@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-dec.h,v 1.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>
* Michel Kaempf <maxx@via.ecp.fr>
......@@ -40,22 +40,25 @@
*****************************************************************************
* 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
{
/* Nothing before this line, the code relies on that */
byte_t * p_buffer; /* raw data packet */
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 ? */
/* Used to chain the packets that carry data for a same PES or PSI */
struct data_packet_s * p_next;
int * pi_refcount;
DATA_PACKET
/* Used to chain the TS packets that carry data for a same PES or PSI */
struct data_packet_s * p_next;
/* Please note that at least one buffer allocator (in particular, the
* Next Generation Buffer Allocator) extends this structure with
* private data after DATA_PACKET. */
} data_packet_t;
/*****************************************************************************
......@@ -66,6 +69,9 @@ typedef struct data_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 */
boolean_t b_data_alignment; /* used to find the beginning of
* a video or audio unit */
......@@ -77,12 +83,15 @@ typedef struct pes_packet_s
int i_rate; /* current pace of reading
* (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
p_next fields of the data_packet_t struct) */
/* Chained list to packets */
data_packet_t * p_first; /* The first packet contained by this
* PES (used by decoders). */
data_packet_t * p_last; /* The last packet contained by this
PES (used by the buffer allocator) */
unsigned int i_nb_data; /* Number of data packets in the chained
list */
} pes_packet_t;
/*****************************************************************************
......@@ -97,9 +106,9 @@ typedef struct decoder_fifo_s
vlc_cond_t data_wait; /* fifo data conditional variable */
/* Data */
pes_packet_t * buffer[FIFO_SIZE + 1];
int i_start;
int i_end;
pes_packet_t * p_first;
pes_packet_t ** pp_last;
int i_depth; /* number of PES packets in the stack */
/* Communication interface between input and decoders */
boolean_t b_die; /* the decoder should return now */
......@@ -110,18 +119,6 @@ typedef struct decoder_fifo_s
/* function to use when releasing a PES */
} decoder_fifo_t;
/* Macros to manage a decoder_fifo_t structure. Please remember to take
* data_lock before using them. */
#define DECODER_FIFO_ISEMPTY( fifo ) ( (fifo).i_start == (fifo).i_end )
#define DECODER_FIFO_ISFULL( fifo ) ( ( ((fifo).i_end + 1 - (fifo).i_start)\
& FIFO_SIZE ) == 0 )
#define DECODER_FIFO_START( fifo ) ( (fifo).buffer[ (fifo).i_start ] )
#define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
& FIFO_SIZE )
#define DECODER_FIFO_END( fifo ) ( (fifo).buffer[ (fifo).i_end ] )
#define DECODER_FIFO_INCEND( fifo ) ( (fifo).i_end = ((fifo).i_end + 1) \
& FIFO_SIZE )
/*****************************************************************************
* bit_fifo_t : bit fifo descriptor
*****************************************************************************
......
......@@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* 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>
*
......@@ -26,7 +26,6 @@
/*
* Communication input -> interface
*/
#define INPUT_MAX_PLUGINS 1
/* FIXME ! */
#define REQUESTED_MPEG 1
#define REQUESTED_AC3 2
......@@ -66,7 +65,6 @@ typedef struct es_descriptor_s
/* PES parser information */
struct pes_packet_s * p_pes; /* Current PES */
struct data_packet_s * p_last; /* The last packet gathered at present */
int i_pes_real_size; /* as indicated by the header */
/* Decoder information */
......@@ -95,6 +93,7 @@ typedef struct es_descriptor_s
#define SPU_ES 0x02
#define NAV_ES 0x03
#define UNKNOWN_ES 0xFF
/*****************************************************************************
* pgrm_descriptor_t
*****************************************************************************
......@@ -263,7 +262,7 @@ typedef struct input_thread_s
/* Read & Demultiplex */
int (* pf_read)( struct input_thread_s *,
struct data_packet_s * pp_packets[] );
struct data_packet_s ** );
void (* pf_demux)( struct input_thread_s *,
struct data_packet_s * );
......@@ -289,8 +288,6 @@ typedef struct input_thread_s
int i_handle; /* socket or file descriptor */
FILE * p_stream; /* if applicable */
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_plugin_data; /* data of the plugin */
......
......@@ -3,7 +3,7 @@
* but exported to plug-ins
*****************************************************************************
* 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>
*
......@@ -27,10 +27,6 @@
*/
/* 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
* of data loss (this should be < 188). */
#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,
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_pes = p_es->p_pes;
if( p_pes != NULL )
{
p_pes->b_discontinuity = 1;
p_es->p_last->p_next = p_pad_data;
p_es->p_last = p_pad_data;
p_pes->p_last->p_next = p_pad_data;
p_pes->p_last = p_pad_data;
p_pes->i_nb_data++;
}
else
{
......@@ -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->p_first = p_pad_data;
p_pes->p_first = p_pes->p_last = p_pad_data;
p_pes->i_nb_data = 1;
p_pes->b_discontinuity = 1;
input_DecodePES( p_es->p_decoder_fifo, p_pes );
}
......@@ -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 */
byte_t * p_buffers; /* Big malloc'ed area */
data_packet_t * p_data; /* malloc'ed area */
pes_packet_t * p_pes; /* malloc'ed area */
struct /* for compatibility with _data_packet_t */
{
/* size of the current buffer (starting right thereafter) */
unsigned int i_size;
} _private;
} _data_buffer_t;
/* FIFOs of free packets */
data_packet_t ** pp_free_data;
pes_packet_t ** pp_free_pes;
struct iovec * p_free_iovec;
/* We overload the data_packet_t type to add private members */
typedef struct _data_packet_s
{
struct _data_packet_s * p_next;
/* FIFO size */
unsigned int i_nb_iovec;
unsigned int i_nb_pes;
unsigned int i_nb_data;
DATA_PACKET
/* Index */
unsigned int i_iovec_start, i_iovec_end;
unsigned int i_data_start, i_data_end;
unsigned int i_pes_start, i_pes_end;
union
{
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;
/* Reference counters for iovec */
unsigned int * pi_refcount;
/* Number of blocs read once by readv */
unsigned int i_read_once;
} netlist_t;
/*****************************************************************************
* input_BuffersInit: initialize the cache structures, return a pointer to it
*****************************************************************************/
#define DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO ) \
static void * input_BuffersInit( void ) \
{ \
_input_buffers_t * p_buffers = malloc( sizeof( _input_buffers_t ) ); \
\
if( p_buffers == NULL ) \
{ \
return( NULL ); \
} \
\
memset( p_buffers, 0, sizeof( _input_buffers_t ) ); \
vlc_mutex_init( &p_buffers->lock ); \
\
return (void *)p_buffers; \
}
/*****************************************************************************
* Prototypes
* input_BuffersEnd: free all cached structures
*****************************************************************************/
#ifndef PLUGIN
int input_NetlistInit( struct input_thread_s *,
int i_nb_iovec,
int i_nb_data,
int i_nb_pes,
size_t i_buffer_size,
int i_read_once );
struct iovec * input_NetlistGetiovec( void * p_method_data );
void input_NetlistMviovec( void * , int,
struct data_packet_s **);
struct data_packet_s * input_NetlistNewPtr( void * );
struct data_packet_s * input_NetlistNewPacket( void *, size_t );
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 * );
#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 @@
(p_symbols)->input_DemuxTS = input_DemuxTS; \
(p_symbols)->input_DemuxPSI = input_DemuxPSI; \
(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_DestroyFifo = aout_DestroyFifo; \
(p_symbols)->vout_CreateThread = vout_CreateThread; \
......
......@@ -2,7 +2,7 @@
* ac3_adec.c: ac3 decoder module main file
*****************************************************************************
* 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>
*
......@@ -171,12 +171,12 @@ static int decoder_Run ( decoder_config_t * p_config )
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->l_end_frame] =
DECODER_FIFO_START(*p_ac3thread->p_fifo)->i_pts;
DECODER_FIFO_START(*p_ac3thread->p_fifo)->i_pts = 0;
p_ac3thread->p_fifo->p_first->i_pts;
p_ac3thread->p_fifo->p_first->i_pts = 0;
} else {
p_ac3thread->p_aout_fifo->date[
p_ac3thread->p_aout_fifo->l_end_frame] =
......
......@@ -2,7 +2,7 @@
* ac3_spdif.c: ac3 pass-through to external decoder with enabled soundcard
*****************************************************************************
* 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>
* Juha Yrjola <jyrjola@cc.hut.fi>
......@@ -347,7 +347,7 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream,
p_bit_stream->p_byte += 3;
p_spdif->i_pts =
DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts;
DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->i_pts = 0;
p_bit_stream->p_decoder_fifo->p_first->i_pts;
p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;
}
}
......@@ -10,7 +10,7 @@
* -dvd_udf to find files
*****************************************************************************
* 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>
*
......@@ -93,10 +93,6 @@
/* how many blocks DVDRead will read in each loop */
#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
......@@ -119,6 +115,21 @@ static int DVDFindCell( thread_dvd_data_t * );
static int DVDFindSector( thread_dvd_data_t * );
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
* we don't pollute the namespace too much.
......@@ -136,10 +147,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_area = DVDSetArea;
input.pf_set_program = DVDSetProgram;
input.pf_demux = input_DemuxPS;
input.pf_new_packet = input_NetlistNewPacket;
input.pf_new_pes = input_NetlistNewPES;
input.pf_delete_packet = input_NetlistDeletePacket;
input.pf_delete_pes = input_NetlistDeletePES;
input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_DeletePES;
input.pf_rewind = DVDRewind;
input.pf_seek = DVDSeek;
#undef input
......@@ -194,33 +205,31 @@ static void DVDInit( input_thread_t * p_input )
}
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;
if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 )
{
intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1;
return;
}
/* We read DVD_BLOCK_READ_ONCE in each loop, so the input will receive
* DVD_DATA_READ_ONCE at most */
/* We read DVD_BLOCK_READ_ONCE in each loop */
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 */
if( IfoCreate( p_dvd ) < 0 )
{
intf_ErrMsg( "dvd error: allcation error in ifo" );
free( p_dvd );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1;
return;
}
......@@ -230,6 +239,7 @@ static void DVDInit( input_thread_t * p_input )
intf_ErrMsg( "dvd error: fatal failure in ifo" );
IfoDestroy( p_dvd->p_ifo );
free( p_dvd );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1;
return;
}
......@@ -289,9 +299,8 @@ static void DVDInit( input_thread_t * p_input )
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->i_part = i_chapter;
/* set title, chapter, audio and subpic */
DVDSetArea( p_input, p_area );
......@@ -322,7 +331,7 @@ static void DVDOpen( struct input_thread_s *p_input )
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
&& !strncasecmp( p_input->p_source, "dvd:", 4 ) )
{
......@@ -383,7 +392,7 @@ static void DVDEnd( input_thread_t * p_input )
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 )
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
* EOF.
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* packets.
*****************************************************************************/
static int DVDRead( input_thread_t * p_input,
data_packet_t ** pp_packets )
data_packet_t ** pp_data )
{
thread_dvd_data_t * p_dvd;
netlist_t * p_netlist;
struct iovec * p_vec;
struct data_packet_s * pp_data[DVD_DATA_READ_ONCE];
struct iovec p_vec[DVD_BLOCK_READ_ONCE];
u8 * pi_cur;
int i_block_once;
int i_packet_size;
......@@ -838,12 +844,12 @@ static int DVDRead( input_thread_t * p_input,
int i_pos;
int i_read_blocks;
int i_sector;
boolean_t b_eof;
boolean_t b_eot;
boolean_t b_eoc;
data_packet_t * p_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;
i_sector = p_dvd->i_title_start + p_dvd->i_sector;
......@@ -861,7 +867,6 @@ static int DVDRead( input_thread_t * p_input,
/* Find cell index in adress map */
if( DVDFindSector( p_dvd ) < 0 )
{
pp_packets[0] = NULL;
intf_ErrMsg( "dvd error: can't find next cell" );
return 1;
}
......@@ -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 );
*/
p_netlist->i_read_once = i_block_once;
/* Get an iovec pointer */
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL )
/* Get iovecs */
*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 */
i_read_blocks = dvdcss_readv( p_dvd->dvdhandle, p_vec,
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 */
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
/* Read headers to compute payload length */
for( i_iovec = 0 ; i_iovec < i_read_blocks ; i_iovec++ )
{
data_packet_t * p_current = p_data;
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;
/*default header */
/* Default header */
if( U32_AT( pi_cur ) != 0x1BA )
{
/* That's the case for all packets, except pack header. */
i_packet_size = U16_AT( pi_cur + 4 );
pp_packets[i_packet] = 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
{
/* MPEG-2 Pack header. */
i_packet_size = 8;
pp_packets[i_packet] = pp_data[i_iovec];
}
pp_packets[i_packet]->p_payload_start =
pp_packets[i_packet]->p_buffer + i_pos;
if( i_pos != 0 )
{
*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_packets[i_packet]->p_payload_start + i_packet_size + 6;
(*pp_data)->p_payload_end =
(*pp_data)->p_payload_start + i_packet_size + 6;
i_packet++;
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 );
......@@ -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;
}
b_eot = !( p_input->stream.p_selected_area->i_tell
< 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 )
if( p_input->stream.p_selected_area->i_tell
>= p_input->stream.p_selected_area->i_size )
{
if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb )
{
/* EOF */
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 1;
return 0;
}
if( b_eot )
{
/* EOT */
intf_WarnMsg( 4, "dvd info: new title" );
p_dvd->i_title++;
DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0;
return( i_packet );
}
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 @@
* It depends on: libdvdread for ifo files and block reading.
*****************************************************************************
* 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>
*
......@@ -85,10 +85,6 @@
/* how many blocks DVDRead will read in each loop */
#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
......@@ -100,6 +96,7 @@ static void DvdReadEnd ( struct input_thread_s * );
static void DvdReadOpen ( struct input_thread_s * );
static void DvdReadClose ( struct input_thread_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 void DvdReadSeek ( struct input_thread_s *, off_t );
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 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
* we don't pollute the namespace too much.
......@@ -123,11 +135,12 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_init_bit_stream = InitBitstream;
input.pf_read = DvdReadRead;
input.pf_set_area = DvdReadSetArea;
input.pf_set_program = DvdReadSetProgram;
input.pf_demux = input_DemuxPS;
input.pf_new_packet = input_NetlistNewPacket;
input.pf_new_pes = input_NetlistNewPES;
input.pf_delete_packet = input_NetlistDeletePacket;
input.pf_delete_pes = input_NetlistDeletePES;
input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_DeletePES;
input.pf_rewind = DvdReadRewind;
input.pf_seek = DvdReadSeek;
#undef input
......@@ -157,7 +170,7 @@ static int DvdReadProbe( probedata_t *p_data )
/* If the user specified "dvdread:" then he probably wants
* to use libdvdread */
i_score = 100;
psz_name += 4;
psz_name += 8;
}
return( i_score );
......@@ -188,24 +201,22 @@ static void DvdReadInit( input_thread_t * p_input )
p_dvd->p_vts_file = NULL;
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
* DVD_DATA_READ_ONCE at most */
p_dvd->i_block_once = DVD_BLOCK_READ_ONCE;
/* this value mustn't be modifed */
p_input->i_read_once = DVD_DATA_READ_ONCE;
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
free( p_dvd );
p_input->b_error = 1;
return;
}
/* Reading structures initialisation */
input_NetlistInit( p_input, DVD_NETLIST_SIZE, 2 * DVD_NETLIST_SIZE,
DVD_NETLIST_SIZE, DVD_VIDEO_LB_LEN, p_dvd->i_block_once );
intf_WarnMsg( 2, "dvdread info: netlist initialized" );
/* We read DVD_BLOCK_READ_ONCE in each loop */
p_dvd->i_block_once = DVD_BLOCK_READ_ONCE;
/* Ifo allocation & initialisation */
if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) )
{
intf_ErrMsg( "dvdread error: can't open VMG info" );
DVDClose( p_dvd->p_dvdread );
input_BuffersEnd( p_input->p_method_data );
free( p_dvd );
p_input->b_error = 1;
return;
......@@ -349,9 +360,16 @@ static void DvdReadEnd( input_thread_t * p_input )
ifoClose( p_dvd->p_vts_file );
ifoClose( p_dvd->p_vmg_file );
/* Close netlist */
input_NetlistEnd( p_input );
p_input->p_method_data = NULL;
input_BuffersEnd( p_input->p_method_data );
}
/*****************************************************************************
* 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
......@@ -511,23 +529,24 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
}
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.i_selected_es_number = 0;
}
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 */
p_input->stream.pp_programs[0]->b_is_ok = 1;
p_input->stream.p_selected_program->b_is_ok = 1;
p_es = NULL;
/* ES 0 -> video MPEG2 */
// 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_type = MPEG2_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 )
case 0x00: /* AC3 */
i_id = ( ( 0x80 + i_position ) << 8 ) | 0xbd;
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_type = AC3_AUDIO_ES;
p_es->b_audio = 1;
......@@ -572,7 +591,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
case 0x03: /* MPEG audio */
i_id = 0xc0 + i_position;
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_type = MPEG2_AUDIO_ES;
p_es->b_audio = 1;
......@@ -586,7 +605,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
i_id = ( ( 0xa0 + i_position ) << 8 ) | 0xbd;
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_type = LPCM_AUDIO_ES;
p_es->b_audio = 1;
......@@ -651,7 +670,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
i_id = ( ( 0x20 + i_position ) << 8 ) | 0xbd;
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_type = DVD_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 )
* EOF.
*****************************************************************************/
static int DvdReadRead( input_thread_t * p_input,
data_packet_t ** pp_packets )
data_packet_t ** pp_data )
{
thread_dvd_data_t * p_dvd;
netlist_t * p_netlist;
u8 p_data[DVD_VIDEO_LB_LEN];
struct iovec * p_vec;
struct data_packet_s * pp_data[DVD_DATA_READ_ONCE];
struct iovec p_vec[DVD_BLOCK_READ_ONCE];
u8 * pi_cur;
int i_blocks;
int i_read;
......@@ -786,9 +803,12 @@ static int DvdReadRead( input_thread_t * p_input,
int i_packet_size;
int i_packet;
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_netlist = (netlist_t *)p_input->p_method_data;
*pp_data = NULL;
/*
* Playback by cell in this pgc, starting at the cell for our chapter.
......@@ -810,8 +830,11 @@ static int DvdReadRead( input_thread_t * p_input,
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 );
if( p_data[41] == 0xbf && p_data[1027] == 0xbf )
{
/*
* Parse the contained dsi packet.
*/
......@@ -825,11 +848,17 @@ static int DvdReadRead( input_thread_t * p_input,
}
assert( p_dvd->i_pack_len < 1024 );
/* Ugly kludge: we send the pack block to the input for it
/* 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_cur_block ++;
p_dvd->i_pack_len++;
}
else
{
b_eot = 1;
p_dvd->i_pack_len = 0;
return 1;
}
}
/*
......@@ -838,13 +867,14 @@ static int DvdReadRead( input_thread_t * p_input,
i_blocks = p_dvd->i_pack_len >= DVD_BLOCK_READ_ONCE
? DVD_BLOCK_READ_ONCE : p_dvd->i_pack_len;
p_dvd->i_pack_len -= i_blocks;
p_netlist->i_read_once = i_blocks;
/* Get an iovec pointer */
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL )
/* Get iovecs */
*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 */
......@@ -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 );
*/
/* 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;
/* Read headers to compute payload length */
for( i_iovec = 0 ; i_iovec < i_read ; i_iovec++ )
{
data_packet_t * p_current = p_data_p;
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;
......@@ -881,35 +908,48 @@ static int DvdReadRead( input_thread_t * p_input,
{
/* That's the case for all packets, except pack header. */
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
{
/* MPEG-2 Pack header. */
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_data)->p_payload_start = (*pp_data)->p_demux_start =
(*pp_data)->p_demux_start + i_pos;
pp_packets[i_packet]->p_payload_start =
pp_packets[i_packet]->p_buffer + i_pos;
pp_packets[i_packet]->p_payload_end =
pp_packets[i_packet]->p_payload_start + i_packet_size + 6;
(*pp_data)->p_payload_end =
(*pp_data)->p_payload_start + i_packet_size + 6;
pp_packets[i_packet]->p_next = NULL;
pp_packets[i_packet]->b_discard_payload = 0;
// pp_packets[i_packet]->p_next = NULL;
// pp_packets[i_packet]->b_discard_payload = 0;
i_packet++;
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 );
......@@ -925,6 +965,24 @@ static int DvdReadRead( input_thread_t * p_input,
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 );
......
......@@ -2,7 +2,7 @@
* lpcm_decoder_thread.c: lpcm decoder thread
*****************************************************************************
* 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>
* Henri Fallon <henri@videolan.org>
......@@ -187,11 +187,11 @@ void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
int i_loop;
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] =
DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts = 0;
p_lpcmdec->p_fifo->p_first->i_pts;
p_lpcmdec->p_fifo->p_first->i_pts = 0;
}
else
{
......
......@@ -62,9 +62,9 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
byte_t buffer[ADEC_FRAME_SIZE];
/* Store time stamp of current frame */
if ( DECODER_FIFO_START(*p_mad_adec->p_fifo)->i_pts ) {
p_mad_adec->i_pts_save = DECODER_FIFO_START(*p_mad_adec->p_fifo)->i_pts;
DECODER_FIFO_START(*p_mad_adec->p_fifo)->i_pts = 0;
if ( p_mad_adec->p_fifo->p_first->i_pts ) {
p_mad_adec->i_pts_save = p_mad_adec->p_fifo->p_first->i_pts;
p_mad_adec->p_fifo->p_first->i_pts = 0;
}
else {
p_mad_adec->i_pts_save = LAST_MDATE;
......
......@@ -2,7 +2,7 @@
* input_es.c: Elementary Stream demux and packet management
*****************************************************************************
* 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>
*
......@@ -75,7 +75,7 @@
*****************************************************************************/
static int ESProbe ( probedata_t * );
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 ESEnd ( struct input_thread_s * );
static void ESSeek ( struct input_thread_s *, off_t );
......@@ -89,6 +89,20 @@ static void ESInitBitstream( struct bit_stream_s *, struct decoder_fifo_s *,
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
* we don't pollute the namespace too much.
......@@ -106,10 +120,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_program = ESSetProgram;
input.pf_read = ESRead;
input.pf_demux = ESDemux;
input.pf_new_packet = input_NetlistNewPacket;
input.pf_new_pes = input_NetlistNewPES;
input.pf_delete_packet = input_NetlistDeletePacket;
input.pf_delete_pes = input_NetlistDeletePES;
input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_DeletePES;
input.pf_rewind = NULL;
input.pf_seek = ESSeek;
#undef input
......@@ -141,27 +155,24 @@ static void ESInit( input_thread_t * p_input )
{
es_descriptor_t * p_es;
p_input->p_method_data = NULL;
/* Initialize netlist */
if( input_NetlistInit( p_input, NB_DATA, NB_DATA, NB_PES, ES_PACKET_SIZE,
INPUT_READ_ONCE ) )
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
intf_ErrMsg( "ES input : Could not initialize netlist" );
p_input->b_error = 1;
return;
}
/* FIXME : detect if InitStream failed */
input_InitStream( p_input, 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 );
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_type = MPEG1_VIDEO_ES;
p_es->i_cat = VIDEO_ES;
input_SelectES( p_input, p_es );
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 );
}
......@@ -170,49 +181,57 @@ static void ESInit( input_thread_t * p_input )
*****************************************************************************/
static void ESEnd( input_thread_t * p_input )
{
input_BuffersEnd( p_input->p_method_data );
}
/*****************************************************************************
* ESRead: reads data packets
*****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of
* EOF.
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* packets.
*****************************************************************************/
static int ESRead( input_thread_t * p_input,
data_packet_t * pp_packets[INPUT_READ_ONCE] )
data_packet_t ** pp_data )
{
int i_read;
struct iovec * p_iovec;
struct iovec p_iovec[ES_READ_ONCE];
data_packet_t * p_data;
/* 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, INPUT_READ_ONCE );
i_read = readv( p_input->i_handle, p_iovec, ES_READ_ONCE );
if( i_read == -1 )
{
intf_ErrMsg( "input error: ES readv error" );
p_input->pf_delete_packet( p_input->p_method_data, p_data );
return( -1 );
}
p_input->stream.p_selected_area->i_tell += i_read;
i_read /= ES_PACKET_SIZE;
/* EOF */
if( i_read == 0 && p_input->stream.b_seekable )
if( i_read != ES_READ_ONCE )
{
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,
(int)(i_read/ES_PACKET_SIZE), pp_packets );
for( i_loop = 0; i_loop < i_read; i_loop++ )
{
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 )
{
pes_packet_t * p_pes = p_input->pf_new_pes( p_input->p_method_data );
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 )
{
......@@ -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->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)
| (input_ClockManageControl( p_input, p_input->stream.pp_programs[0],
if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
| (input_ClockManageControl( p_input,
p_input->stream.p_selected_program,
(mtime_t)0 ) == PAUSE_S) )
{
intf_WarnMsg( 2, "synchro reinit" );
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 );
vlc_mutex_lock( &p_fifo->data_lock );
if( ( (DECODER_FIFO_END( *p_fifo ) - DECODER_FIFO_START( *p_fifo ))
& FIFO_SIZE ) >= MAX_PACKETS_IN_FIFO )
if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
{
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
}
......@@ -290,18 +310,23 @@ static void ESNextDataPacket( bit_stream_t * p_bit_stream )
* time to jump to the next PES packet */
if( p_bit_stream->p_data->p_next == NULL )
{
/* We are going to read/write the start and end indexes of the
* decoder fifo and to use the fifo's conditional variable,
* that's why we need to take the lock before. */
pes_packet_t * p_next;
vlc_mutex_lock( &p_fifo->data_lock );
/* 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,
DECODER_FIFO_START( *p_fifo ) );
DECODER_FIFO_INCSTART( *p_fifo );
p_fifo->p_first );
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. */
vlc_cond_signal( &p_fifo->data_wait );
......@@ -310,7 +335,7 @@ static void ESNextDataPacket( bit_stream_t * p_bit_stream )
}
/* 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 );
......
......@@ -2,7 +2,7 @@
* input_es.h: thread structure of the ES plugin
*****************************************************************************
* 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:
*
......@@ -20,8 +20,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define NB_DATA 8192
#define NB_PES 4096
#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 @@
* input_ps.c: PS demux and packet management
*****************************************************************************
* 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>
* 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 )
*****************************************************************************/
static int PSProbe ( probedata_t * );
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 PSEnd ( struct input_thread_s * );
static int PSSetProgram ( struct input_thread_s * , pgrm_descriptor_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 * );
static void DeletePES ( void *, struct pes_packet_s * );
/*****************************************************************************
* 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, 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
......@@ -113,10 +123,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_program = PSSetProgram;
input.pf_read = PSRead;
input.pf_demux = input_DemuxPS;
input.pf_new_packet = NewPacket;
input.pf_new_pes = NewPES;
input.pf_delete_packet = DeletePacket;
input.pf_delete_pes = DeletePES;
input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_DeletePES;
input.pf_rewind = NULL;
input.pf_seek = PSSeek;
#undef input
......@@ -158,64 +168,11 @@ static int PSProbe( probedata_t *p_data )
*****************************************************************************/
static void PSInit( input_thread_t * p_input )
{
packet_cache_t * p_packet_cache;
/* 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;
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 )
if( (p_input->p_method_data = input_BuffersInit()) == 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 )
{
......@@ -225,6 +182,7 @@ static void PSInit( input_thread_t * p_input )
if( p_input->p_stream == NULL )
{
intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
input_BuffersEnd( p_input->p_method_data );
p_input->b_error = 1;
return;
}
......@@ -253,11 +211,22 @@ static void PSInit( input_thread_t * p_input )
while( !p_input->b_die && !p_input->b_error
&& !p_demux_data->b_has_PSM )
{
int i_result, i;
data_packet_t * pp_packets[INPUT_READ_ONCE];
int i_result;
data_packet_t * p_data;
data_packet_t * p_saved_data;
i_result = PSRead( p_input, &p_data );
p_saved_data = p_data;
while( p_data != NULL )
{
input_ParsePS( p_input, p_data );
p_data = p_data->p_next;
}
i_result = PSRead( p_input, pp_packets );
if( i_result == 1 )
p_input->pf_delete_packet( p_input->p_method_data, p_saved_data );
if( i_result == 0 )
{
/* EOF */
vlc_mutex_lock( &p_input->stream.stream_lock );
......@@ -265,19 +234,12 @@ static void PSInit( input_thread_t * p_input )
vlc_mutex_unlock( &p_input->stream.stream_lock );
break;
}
if( i_result == -1 )
else if( i_result == -1 )
{
p_input->b_error = 1;
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. */
if( p_input->stream.p_selected_area->i_tell >
INPUT_PREPARSE_LENGTH )
......@@ -388,22 +350,7 @@ static void PSInit( 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)
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 );
input_BuffersEnd( p_input->p_method_data );
}
/*****************************************************************************
......@@ -418,7 +365,7 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
{
if( feof( p_input->p_stream ) )
{
return( 1 );
return( 0 );
}
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,
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell += i_len;
vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 0 );
return( i_len );
}
/*****************************************************************************
* PSRead: reads data packets
*****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of
* EOF.
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* packets.
*****************************************************************************/
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];
data_packet_t * p_data;
size_t i_packet_size;
int i_packet, i_error;
memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
*pp_data = NULL;
for( i_packet = 0; i_packet < PS_READ_ONCE; i_packet++ )
{
/* 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 );
}
......@@ -480,7 +428,7 @@ static int PSRead( input_thread_t * p_input,
}
else
{
return( 1 );
return( 0 );
}
}
/* Packet found. */
......@@ -491,7 +439,7 @@ static int PSRead( input_thread_t * p_input,
if( U32_AT(p_header) != 0x1B9 )
{
/* 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 );
}
......@@ -528,7 +476,8 @@ static int PSRead( input_thread_t * p_input,
}
/* 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 )
{
intf_ErrMsg( "Out of memory" );
......@@ -538,25 +487,29 @@ static int PSRead( input_thread_t * p_input,
if( U32_AT(p_header) != 0x1B9 )
{
/* 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. */
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 );
}
/* In MPEG-2 pack headers we still have to read stuffing bytes. */
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 */
byte_t p_garbage[8];
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 );
}
}
......@@ -565,14 +518,15 @@ static int PSRead( input_thread_t * p_input,
else
{
/* 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. */
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 )
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 @@
* input_ps.h: thread structure of the PS plugin
*****************************************************************************
* 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>
* Cyril Deguet <asmax@via.ecp.fr>
......@@ -22,54 +22,5 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define DATA_CACHE_SIZE 150
#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;
#define PS_READ_ONCE 50
......@@ -2,7 +2,7 @@
* input_ts.c: TS demux and netlist management
*****************************************************************************
* 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>
*
......@@ -89,7 +89,21 @@ static int TSProbe ( probedata_t * );
static void TSInit ( struct input_thread_s * );
static void TSEnd ( 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
......@@ -108,10 +122,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_program = input_SetProgram;
input.pf_read = TSRead;
input.pf_demux = input_DemuxTS;
input.pf_new_packet = input_NetlistNewPacket;
input.pf_new_pes = input_NetlistNewPES;
input.pf_delete_packet = input_NetlistDeletePacket;
input.pf_delete_pes = input_NetlistDeletePES;
input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_DeletePES;
input.pf_rewind = NULL;
input.pf_seek = NULL;
#undef input
......@@ -160,7 +174,6 @@ static int TSProbe( probedata_t * p_data )
*****************************************************************************/
static void TSInit( input_thread_t * p_input )
{
/* Initialize netlist and TS structures */
thread_ts_data_t * p_method;
es_descriptor_t * p_pat_es;
es_ts_data_t * p_demux_data;
......@@ -184,11 +197,9 @@ static void TSInit( input_thread_t * p_input )
p_input->p_method_data = NULL;
/* Initialize netlist */
if( input_NetlistInit( p_input, NB_DATA, NB_DATA, NB_PES, TS_PACKET_SIZE,
INPUT_READ_ONCE ) )
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
intf_ErrMsg( "TS input : Could not initialize netlist" );
p_input->b_error = 1;
return;
}
......@@ -227,23 +238,23 @@ static void TSEnd( input_thread_t * p_input )
input_DelES( p_input, p_pat_es );
free(p_input->p_plugin_data);
input_NetlistEnd( p_input );
input_BuffersEnd( p_input->p_method_data );
}
/*****************************************************************************
* TSRead: reads data packets
*****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of
* EOF.
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* packets.
*****************************************************************************/
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;
unsigned int i_loop;
int i_read;
int i_read = 0, i_loop;
int i_data = 1;
struct iovec * p_iovec;
struct iovec p_iovec[TS_READ_ONCE];
data_packet_t * p_data;
struct timeval timeout;
/* Init */
......@@ -257,9 +268,6 @@ static int TSRead( input_thread_t * p_input,
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
/* Reset pointer table */
memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
/* Fill if some data is available */
#if defined( WIN32 )
if ( ! p_input->stream.b_pace_control )
......@@ -278,25 +286,26 @@ static int TSRead( input_thread_t * p_input,
if( i_data )
{
/* 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( 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
{
i_read = readv_network( p_input->i_handle, p_iovec,
INPUT_READ_ONCE, p_method );
TS_READ_ONCE, p_method );
}
#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 */
if( (i_read == -1) && ( (errno == EAGAIN) || (errno = EWOULDBLOCK) ) )
......@@ -306,36 +315,35 @@ static int TSRead( input_thread_t * p_input,
i_read = 0;
}
#endif
/* Error */
if( i_read == -1 )
{
intf_ErrMsg( "input error: TS readv error" );
p_input->pf_delete_packet( p_input->p_method_data, p_data );
return( -1 );
}
p_input->stream.p_selected_area->i_tell += i_read;
i_read /= TS_PACKET_SIZE;
/* EOF */
if( i_read == 0 && p_input->stream.b_seekable )
/* Check correct TS header */
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_data)->p_demux_start[0] != 0x47 )
{
if( pp_packets[i_loop]->p_buffer[0] != 0x47 )
intf_ErrMsg( "input error: bad TS packet (starts with "
"0x%.2x, should be 0x47)",
pp_packets[i_loop]->p_buffer[0] );
p_data->p_demux_start[0] );
}
for( ; i_loop < INPUT_READ_ONCE ; i_loop++ )
{
pp_packets[i_loop] = NULL;
pp_data = &(*pp_data)->p_next;
}
p_input->stream.p_selected_area->i_tell += i_read;
if( i_read != TS_READ_ONCE )
{
/* Delete remaining packets */
p_input->pf_delete_packet( p_input->p_method_data, *pp_data );
*pp_data = NULL;
}
}
return 0;
return( i_read );
}
......@@ -2,7 +2,7 @@
* input_ts.h: structures of the input not exported to other modules
*****************************************************************************
* 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>
* Boris Dors <babal@via.ecp.fr>
......@@ -22,10 +22,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define NB_DATA 16384
#define NB_PES 8192
/* UDP packets contain 1500 bytes, that is 7 TS packets */
#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
......
......@@ -2,7 +2,7 @@
* mpeg_adec.c: MPEG audio decoder thread
*****************************************************************************
* 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>
* Michel Lespinasse <walken@via.ecp.fr>
......@@ -203,11 +203,11 @@ static void DecodeThread( adec_thread_t * p_adec )
buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
+ (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] =
DECODER_FIFO_START( *p_adec->p_fifo )->i_pts;
DECODER_FIFO_START(*p_adec->p_fifo)->i_pts = 0;
p_adec->p_fifo->p_first->i_pts;
p_adec->p_fifo->p_first->i_pts = 0;
}
else
{
......
......@@ -2,7 +2,7 @@
* video_parser.c : video parser thread
*****************************************************************************
* 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>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -281,38 +281,6 @@ static int InitThread( vpar_thread_t *p_vpar )
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
*****************************************************************************
......@@ -428,13 +396,13 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream,
if( b_new_pes )
{
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 =
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 =
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
intf_DbgMsg( "Discontinuity in BitstreamCallback" );
......
......@@ -2,7 +2,7 @@
* spu_decoder.c : spu decoder thread
*****************************************************************************
* 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>
*
......@@ -275,7 +275,7 @@ static void ParsePacket( spudec_thread_t *p_spudec )
p_spudec->i_spu_size );
/* 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" );
return;
......@@ -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. */
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 */
p_src = malloc( p_spudec->i_rle_size );
......
......@@ -70,17 +70,14 @@
#include "modules.h"
#include "modules_export.h"
#include "../mpeg/input_ps.h"
#include "input_vcd.h"
#include "linux_cdrom_tools.h"
/* 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 BUFFER_SIZE VCD_DATA_SIZE
/*****************************************************************************
* Local prototypes
*****************************************************************************/
......@@ -95,11 +92,19 @@ static void VCDClose ( struct input_thread_s *);
static void VCDEnd ( struct input_thread_s *);
static void VCDSeek ( struct input_thread_s *, off_t );
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 )
input.pf_set_area = VCDSetArea;
input.pf_set_program = VCDSetProgram;
input.pf_demux = input_DemuxPS;
input.pf_new_packet = NewPacket;
input.pf_new_pes = NewPES;
input.pf_delete_packet = DeletePacket;
input.pf_delete_pes = DeletePES;
input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_DeletePES;
input.pf_rewind = VCDRewind;
input.pf_seek = VCDSeek;
#undef input
......@@ -162,8 +167,6 @@ static int VCDProbe( probedata_t *p_data )
*****************************************************************************/
static void VCDOpen( struct input_thread_s *p_input )
{
int vcdhandle;
vlc_mutex_lock( &p_input->stream.stream_lock );
/* If we are here we can control the pace... */
......@@ -171,7 +174,6 @@ static void VCDOpen( struct input_thread_s *p_input )
p_input->stream.b_seekable = 1;
p_input->stream.p_selected_area->i_size = 0;
p_input->stream.p_selected_area->i_tell = 0;
vlc_mutex_unlock( &p_input->stream.stream_lock );
......@@ -181,20 +183,17 @@ static void VCDOpen( struct input_thread_s *p_input )
if( strlen( p_input->p_source ) > 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
{
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;
return;
}
p_input->i_handle = (int) vcdhandle;
}
/*****************************************************************************
......@@ -216,7 +215,6 @@ static void VCDInit( input_thread_t * p_input )
int i;
input_area_t * p_area;
es_descriptor_t * p_es;
packet_cache_t * p_packet_cache;
p_vcd = malloc( sizeof(thread_vcd_data_t) );
......@@ -227,78 +225,35 @@ static void VCDInit( input_thread_t * p_input )
return;
}
p_input->p_plugin_data = (void *)p_vcd;
p_input->p_method_data = NULL;
p_vcd->vcdhandle = p_input->i_handle;
p_vcd->b_end_of_track = 0;
/* we read the Table Of Content information */
if ( read_toc(p_vcd) == -1 )
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
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" );
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" );
free( p_vcd );
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;
p_vcd->i_handle = p_input->i_handle;
/* 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 )
/* We read the Table Of Content information */
p_vcd->nb_tracks = ioctl_GetTrackCount( p_input->i_handle );
if( p_vcd->nb_tracks < 0 )
{
intf_ErrMsg( "Out of memory" );
input_BuffersEnd( p_input->p_method_data );
free( p_vcd );
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 )
p_vcd->p_sectors = ioctl_GetSectors( p_input->i_handle );
if ( p_vcd->p_sectors == NULL )
{
intf_ErrMsg( "Out of memory" );
input_BuffersEnd( p_input->p_method_data );
free( p_vcd );
p_input->b_error = 1;
return;
}
p_packet_cache->largebuffer.l_index = 0;
/* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock );
......@@ -309,7 +264,6 @@ static void VCDInit( input_thread_t * p_input )
/* disc input method */
p_input->stream.i_method = INPUT_METHOD_VCD;
#define area p_input->stream.pp_areas
for( i = 1 ; i <= p_vcd->nb_tracks - 1 ; i++ )
{
......@@ -319,8 +273,9 @@ static void VCDInit( input_thread_t * p_input )
area[i]->i_id = i;
/* Absolute start offset and size */
area[i]->i_start = p_vcd->tracks_sector[i];
area[i]->i_size = p_vcd->tracks_sector[i+1] - 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 = (off_t)(p_vcd->p_sectors[i+1] - p_vcd->p_sectors[i])
* (off_t)VCD_DATA_SIZE;
/* Number of chapters */
area[i]->i_part_nb = 0; // will be the entry points
......@@ -330,18 +285,18 @@ static void VCDInit( input_thread_t * p_input )
area[i]->i_angle_nb = 1; // no angle support in VCDs
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
/* Get requested title - if none try the first title */
i_title = main_GetIntVariable( INPUT_TITLE_VAR, 1 );
if( i_title <= 0)
if( i_title <= 0 )
{
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 */
i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 );
......@@ -350,7 +305,6 @@ static void VCDInit( input_thread_t * p_input )
i_chapter = 1;
}
p_input->stream.pp_areas[i_title]->i_part = i_chapter;
p_area = p_input->stream.pp_areas[i_title];
......@@ -362,7 +316,7 @@ static void VCDInit( input_thread_t * p_input )
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 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_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xe0, 0 );
......@@ -375,8 +329,7 @@ static void VCDInit( input_thread_t * p_input )
input_SelectES( p_input, p_es );
}
p_es = input_AddES( p_input,
p_input->stream.p_selected_program, 0xc0, 0 );
p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xc0, 0 );
p_es->i_stream_id = 0xc0;
p_es->i_type = MPEG1_AUDIO_ES;
p_es->b_audio = 1;
......@@ -388,12 +341,8 @@ static void VCDInit( input_thread_t * p_input )
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
return;
}
/*****************************************************************************
* VCDEnd: frees unused data
*****************************************************************************/
......@@ -401,10 +350,11 @@ static void VCDEnd( input_thread_t * p_input )
{
thread_vcd_data_t * p_vcd;
input_BuffersEnd( p_input->p_method_data );
p_vcd = (thread_vcd_data_t*)p_input->p_plugin_data;
free( p_vcd );
}
/*****************************************************************************
......@@ -430,10 +380,10 @@ static int VCDSetArea( input_thread_t * p_input, input_area_t * p_area )
/* we can't use the interface slider until initilization is complete */
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 */
p_input->stream.p_selected_area->i_part = 0;
/* Reset the Chapter position of the current title */
p_input->stream.p_selected_area->i_part = 1;
p_input->stream.p_selected_area->i_tell = 0;
/* Change the default area */
......@@ -441,115 +391,102 @@ static int VCDSetArea( input_thread_t * p_input, input_area_t * p_area )
/* Change the current track */
/* The first track is not a valid one */
p_vcd->current_track = p_area->i_id ;
p_vcd->current_sector = p_vcd->tracks_sector[p_vcd->current_track] ;
p_vcd->i_track = p_area->i_id;
p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track];
}
/* warn interface that something has changed */
p_input->stream.b_seekable = 1;
p_input->stream.b_changed = 1;
return 0 ;
return 0;
}
/*****************************************************************************
* VCDRead: reads from the VCD into PES packets.
*****************************************************************************
* Returns -1 in case of error, 0 if everything went well, and 1 in case of
* EOF.
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* packets.
*****************************************************************************/
static int VCDRead( input_thread_t * p_input,
data_packet_t ** pp_packets )
static int VCDRead( input_thread_t * p_input, data_packet_t ** pp_data )
{
thread_vcd_data_t * p_vcd;
data_packet_t * p_data;
int i_packet_size;
int i_index;
int i_packet;
boolean_t b_eof;
byte_t * p_buffer;
boolean_t b_no_packet;
u32 i_header;
byte_t p_buffer[ VCD_DATA_SIZE ];
boolean_t b_eot = 0; /* end of track */
/* boolean_t b_eoc; No chapters yet */
p_vcd = (thread_vcd_data_t *)p_input->p_plugin_data;
p_buffer = malloc ( VCD_DATA_SIZE );
if ( p_buffer == NULL )
{
intf_ErrMsg("Could not malloc the read buffer");
return -1;
}
i_packet = 0;
b_no_packet = 0;
*pp_data = NULL;
while( i_packet < VCD_DATA_ONCE )
{
i_index = 0;
if ( VCD_sector_read( p_vcd, p_buffer ) == -1 )
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;
}
while (i_index < BUFFER_SIZE - 6)
{
p_vcd->i_sector++;
if( (U32_AT(p_buffer + i_index) & 0xFFFFFF00) != 0x100L )
if( p_vcd->i_sector >= p_vcd->p_sectors[p_vcd->i_track + 1] )
{
/* This is not the startcode of a packet. Read the stream
* until we find one. */
b_eot = 1;
break;
}
if( !U32_AT( p_buffer + i_index ) )
i_index = 0;
while( i_index < BUFFER_SIZE-6 && i_packet < VCD_DATA_ONCE )
{
i_header = U32_AT(p_buffer + i_index);
/* 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. */
intf_WarnMsg( 3, "Garbage at input" );
while( !i_header && (++i_index < BUFFER_SIZE - 4) )
{
i_header = U32_AT(p_buffer + i_index);
}
while( ( (U32_AT(p_buffer + i_index) & 0xFFFFFF00) != 0x100L )
&& ( i_index < BUFFER_SIZE - 4 ) )
if( !i_header )
{
i_index ++;
intf_WarnMsg( 12, "vcd warning: zero-padded packet" );
break;
}
if ( i_index == BUFFER_SIZE - 4 )
/* Read the stream until we find a startcode. */
while( (i_header & 0xFFFFFF00) != 0x100L
&& (++i_index < BUFFER_SIZE - 4) )
{
b_no_packet = 1;
}
/* Packet found. */
i_header = U32_AT(p_buffer + i_index);
}
if (b_no_packet)
if( (i_header & 0xFFFFFF00) != 0x100L )
{
b_no_packet = 0;
intf_WarnMsg(3, "No packet found on sector %d\n",
p_vcd->current_sector -1 );
intf_WarnMsg( 3, "vcd warning: no packet at sector %d",
p_vcd->i_sector - 1 );
break; /* go to the next sector */
}
#ifdef DEBUG
intf_DbgMsg("packet start code : %X\n",
U32_AT(p_buffer + i_index));
#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. */
intf_DbgMsg( "packet start code : %X", i_header );
if( U32_AT(p_buffer + i_index) != 0x1BA )
{
/* That's the case for all packets, except pack header. */
i_packet_size = U16_AT((p_buffer + ( i_index + 4 )));
}
else
switch( i_header )
{
/* Pack header. */
/* 0x1b9 == SYSTEM_END_CODE, it is only 4 bytes long. */
case 0x1b9:
i_packet_size = -2;
break;
/* Pack header */
case 0x1ba:
if( ( *( p_buffer + ( i_index + 4 ) ) & 0xC0) == 0x40 )
{
/* MPEG-2 */
......@@ -562,99 +499,99 @@ static int VCDRead( input_thread_t * p_input,
}
else
{
intf_ErrMsg( "Unable to determine stream type" );
intf_ErrMsg( "vcd error: unable to determine "
"stream type" );
return( -1 );
}
break;
/* The packet is at least 6 bytes long. */
default:
/* That's the case for all packets, except pack header. */
i_packet_size = U16_AT((p_buffer + ( i_index + 4 )));
break;
}
}
else
{
/* System End Code */
i_packet_size = -2;
}
#ifdef DEBUG
intf_DbgMsg("i_index : %d\n", i_index);
intf_DbgMsg("i_packet_size : %d\n", i_packet_size);
#endif
intf_DbgMsg( "i_index : %d", i_index );
intf_DbgMsg( "i_packet_size : %d", i_packet_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;
}
/* 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 )
{
intf_ErrMsg( "Out of memory" );
intf_ErrMsg( "vcd error: out of memory" );
return( -1 );
}
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 );
i_index += ( 6 + i_packet_size );
}
else
{
/* 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;
}
/* Give the packet to the other input stages. */
pp_packets[i_packet] = p_data;
i_packet ++;
}
*pp_data = p_data;
pp_data = &p_data->p_next;
if ( p_vcd->b_end_of_track )
break;
i_packet++;
}
}
pp_packets[i_packet] = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell =
p_vcd->current_sector -
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;
/* 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
* some modification from the interface *
/* We modify i_part only at end of chapter not to erase
* some modification from the interface */
p_input->stream.p_selected_area->i_part = p_vcd->i_chapter;
}*/
}
#endif
b_eof = p_vcd->b_end_of_track
&& ( ( p_vcd->current_track ) >= p_vcd->nb_tracks - 1);
if( b_eot )
{
input_area_t *p_area;
if( b_eof )
/* EOF ? */
if( p_vcd->i_track >= p_vcd->nb_tracks - 1 )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 1;
return 0;
}
if( p_vcd->b_end_of_track )
{
intf_WarnMsg( 4, "vcd info: new title" );
p_vcd->b_end_of_track = 0;
VCDSetArea( 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;
p_area = p_input->stream.pp_areas[
p_input->stream.p_selected_area->i_id + 1 ];
p_area->i_part = 1;
VCDSetArea( p_input, p_area );
}
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 )
return( -1 );
}
/****************************************************************************
* VCDSeek
****************************************************************************/
......@@ -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->current_sector = p_vcd->tracks_sector[p_vcd->current_track]
+ i_off;
p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track]
+ 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 =
(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 @@
* input_vcd.h: thread structure of the VCD plugin
*****************************************************************************
* 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>
*
......@@ -21,25 +21,17 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
/*****************************************************************************
* thread_vcd_data_t: VCD information
*****************************************************************************/
typedef struct thread_vcd_data_s
{
int vcdhandle; // File descriptor
int nb_tracks; // Nb of tracks (titles)
int current_track; // Current track
int current_sector; // Current Sector
int * tracks_sector; // index of tracks
boolean_t b_end_of_track; // if the end of track is
// reached
} thread_vcd_data_t ;
int i_handle; /* File descriptor */
int nb_tracks; /* Nb of tracks (titles) */
int i_track; /* Current track */
int i_sector; /* Current Sector */
int * p_sectors; /* Track sectors */
boolean_t b_end_of_track; /* If the end of track was reached */
} thread_vcd_data_t;
......@@ -71,129 +71,97 @@
#include "modules.h"
#include "modules_export.h"
#include "input_vcd.h"
#include "linux_cdrom_tools.h"
/*****************************************************************************
* read_toc : Reads the Table of Content of a CD-ROM and fills p_vcd with *
* the read information *
*****************************************************************************/
int read_toc ( thread_vcd_data_t * p_vcd )
* ioctl_ReadTocHeader: Read the TOC header and return the track number.
*****************************************************************************/
int ioctl_GetTrackCount( int i_fd )
{
int i ;
struct cdrom_tochdr tochdr ;
struct cdrom_tocentry tocent ;
int fd = p_vcd->vcdhandle ;
struct cdrom_tochdr tochdr;
/* first we read the TOC header */
if (ioctl(fd, CDROMREADTOCHDR, &tochdr) == -1)
/* First we read the TOC header */
if( ioctl( i_fd, CDROMREADTOCHDR, &tochdr ) == -1 )
{
intf_ErrMsg("problem occured when reading CD's TOCHDR\n") ;
return -1 ;
}
p_vcd->nb_tracks = tochdr.cdth_trk1;
/* 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 ) );
if ( p_vcd->tracks_sector == NULL )
{
intf_ErrMsg("could not malloc tracks_sector");
intf_ErrMsg( "vcd error: could not read TOCHDR" );
return -1;
}
/* then for each track we read its TOC entry */
return tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
}
for( i=tochdr.cdth_trk0 ; i <= tochdr.cdth_trk1 ; i++ )
{
tocent.cdte_track = i;
tocent.cdte_format = CDROM_LBA;
if (ioctl( fd, CDROMREADTOCENTRY, &tocent) == -1 )
/*****************************************************************************
* ioctl_GetSectors: Read the Table of Contents and fill p_vcd.
*****************************************************************************/
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( "problem occured when reading CD's TOCENTRY\n" );
free ( p_vcd->tracks_sector );
return -1;
intf_ErrMsg( "vcd error: could not read TOCHDR" );
return NULL;
}
p_vcd->tracks_sector[i-1] = tocent.cdte_addr.lba ;
i_tracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
p_sectors = malloc( (i_tracks + 1) * sizeof(int) );
if( p_sectors == NULL )
{
intf_ErrMsg( "vcd error: could not allocate p_sectors" );
return NULL;
}
/* finally we read the lead-out track toc entry */
/* Fill the p_sectors structure with the track/sector matches */
for( i = 0 ; i <= i_tracks ; i++ )
{
tocent.cdte_format = CDROM_LBA;
tocent.cdte_track =
( i == i_tracks ) ? CDROM_LEADOUT : tochdr.cdth_trk0 + i;
tocent.cdte_track = CDROM_LEADOUT ;
tocent.cdte_format = CDROM_LBA ;
if (ioctl(fd, CDROMREADTOCENTRY, &tocent) == -1)
if( ioctl( i_fd, CDROMREADTOCENTRY, &tocent ) == -1 )
{
intf_ErrMsg("problem occured when readind CD's
lead-out track TOC entry") ;
free (p_vcd->tracks_sector) ;
return -1 ;
intf_ErrMsg( "vcd error: could not read TOCENTRY" );
free( p_sectors );
return NULL;
}
p_vcd->tracks_sector[p_vcd->nb_tracks] = tocent.cdte_addr.lba ;
return 1 ;
p_sectors[ i ] = tocent.cdte_addr.lba;
}
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] ;
struct cdrom_msf0 msf_cursor ;
msf_cursor = lba2msf( p_vcd->current_sector ) ;
#ifdef DEBUG
intf_DbgMsg("Playing frame %d:%d-%d\n", msf_cursor.minute,
msf_cursor.second, msf_cursor.frame) ;
#endif
memcpy(p_read_block, &msf_cursor, sizeof(struct cdrom_msf0)) ;
if (ioctl(p_vcd->vcdhandle, CDROMREADRAW, p_read_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 );
byte_t p_block[ VCD_SECTOR_SIZE ];
int i_dummy = i_sector + 2 * CD_FRAMES;
#define p_msf ((struct cdrom_msf0 *)p_block)
p_msf->minute = i_dummy / (CD_FRAMES * CD_SECS);
p_msf->second = ( i_dummy % (CD_FRAMES * CD_SECS) ) / CD_FRAMES;
p_msf->frame = ( i_dummy % (CD_FRAMES * CD_SECS) ) % CD_FRAMES;
p_vcd->current_sector ++;
intf_DbgMsg( "vcd debug: playing frame %d:%d-%d",
p_msf->minute, p_msf->second, p_msf->frame);
#undef p_msf
if ( p_vcd->current_sector ==
p_vcd->tracks_sector[p_vcd->current_track + 1] )
if( ioctl(i_fd, CDROMREADRAW, p_block) == -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;
}
/*****************************************************************************
* 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*/
/* 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 );
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 ;
return 0;
}
......@@ -36,7 +36,6 @@
/******************************************************************************
* Prototypes *
******************************************************************************/
int read_toc ( struct thread_vcd_data_s *);
int VCD_sector_read ( struct thread_vcd_data_s *, byte_t *) ;
struct cdrom_msf0 lba2msf ( int ) ;
int ioctl_GetTrackCount ( int );
int * ioctl_GetSectors ( int );
int ioctl_ReadSector ( int, int, byte_t * );
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* 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>
*
......@@ -120,9 +120,6 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
return( NULL );
}
/* Packets read once */
p_input->i_read_once = INPUT_READ_ONCE;
/* Initialize thread properties */
p_input->b_die = 0;
p_input->b_error = 0;
......@@ -206,7 +203,7 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
/* Request thread destruction */
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_cond_signal( &p_input->stream.stream_wait );
vlc_mutex_unlock( &p_input->stream.stream_lock );
......@@ -229,9 +226,6 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
*****************************************************************************/
static void RunThread( input_thread_t *p_input )
{
int i_error, i;
data_packet_t ** pp_packets;
if( InitThread( p_input ) )
{
/* If we failed, wait before we are killed, and exit */
......@@ -242,22 +236,16 @@ static void RunThread( input_thread_t *p_input )
return;
}
/* initialization is completed */
/* initialization is complete */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_changed = 1;
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 )
{
data_packet_t * p_data;
int i_count, i;
p_input->c_loops++;
vlc_mutex_lock( &p_input->stream.stream_lock );
......@@ -357,32 +345,32 @@ static void RunThread( input_thread_t *p_input )
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. */
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->pf_demux( p_input, pp_packets[i] );
p_input->pf_demux( p_input, p_data );
p_data = p_next;
}
if( i_error )
{
if( i_error == 1 )
if( i_count == 0 && p_input->stream.b_seekable )
{
/* End of file - we do not set b_die because only the
* interface is allowed to do so. */
intf_WarnMsg( 3, "input: EOF reached" );
p_input->b_eof = 1;
}
else
else if( i_count < 0 )
{
p_input->b_error = 1;
}
}
}
free( pp_packets );
if( p_input->b_error || p_input->b_eof )
{
......@@ -401,7 +389,6 @@ static void RunThread( input_thread_t *p_input )
*****************************************************************************/
static int InitThread( input_thread_t * p_input )
{
/* Initialize statistics */
p_input->c_loops = 0;
p_input->stream.c_packets_read = 0;
......
......@@ -2,7 +2,7 @@
* input_dec.c: Functions for the management of decoders
*****************************************************************************
* 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>
*
......@@ -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 );
if( !DECODER_FIFO_ISFULL( *p_decoder_fifo ) )
{
p_decoder_fifo->buffer[p_decoder_fifo->i_end] = p_pes;
DECODER_FIFO_INCEND( *p_decoder_fifo );
p_pes->p_next = NULL;
*p_decoder_fifo->pp_last = p_pes;
p_decoder_fifo->pp_last = &p_pes->p_next;
p_decoder_fifo->i_depth++;
/* Warn the decoder that it's got work to do. */
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 );
}
......@@ -261,7 +253,9 @@ static decoder_config_t * CreateDecoderConfig( input_thread_t * p_input,
p_config->i_type = p_es->i_type;
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->p_packets_mgt = p_input->p_method_data;
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,
*****************************************************************************/
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. */
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,
DECODER_FIFO_START( *p_config->p_decoder_fifo ) );
DECODER_FIFO_INCSTART( *p_config->p_decoder_fifo );
}
p_config->p_decoder_fifo->p_first );
/* Destroy the lock and cond */
vlc_cond_destroy( &p_config->p_decoder_fifo->data_wait );
......
......@@ -2,7 +2,7 @@
* input_ext-dec.c: services to the decoders
*****************************************************************************
* 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>
*
......@@ -55,7 +55,7 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
/* Get the first data packet. */
vlc_mutex_lock( &p_fifo->data_lock );
while ( DECODER_FIFO_ISEMPTY( *p_fifo ) )
while ( p_fifo->p_first == NULL )
{
if ( p_fifo->b_die )
{
......@@ -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 );
}
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_end = p_bit_stream->p_data->p_payload_end;
p_bit_stream->fifo.buffer = 0;
......@@ -100,12 +100,7 @@ void DecoderError( decoder_fifo_t * p_fifo )
while( !p_fifo->b_die )
{
/* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY(*p_fifo) )
{
p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_fifo) );
DECODER_FIFO_INCSTART( *p_fifo );
}
p_fifo->pf_delete_pes( p_fifo->p_packets_mgt, p_fifo->p_first );
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
......@@ -131,24 +126,29 @@ void NextDataPacket( bit_stream_t * p_bit_stream )
* time to jump to the next PES packet */
if( p_bit_stream->p_data->p_next == NULL )
{
/* We are going to read/write the start and end indexes of the
* decoder fifo and to use the fifo's conditional variable,
* that's why we need to take the lock before. */
pes_packet_t * p_next;
vlc_mutex_lock( &p_fifo->data_lock );
/* 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,
DECODER_FIFO_START( *p_fifo ) );
DECODER_FIFO_INCSTART( *p_fifo );
p_fifo->p_first );
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. */
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
}
/* 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 );
......
/*****************************************************************************
* 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 @@
* mpeg_system.c: TS, PS and PES management
*****************************************************************************
* 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>
* Michel Lespinasse <walken@via.ecp.fr>
......@@ -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 )
!= 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_pes = NULL;
return;
......@@ -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)) )
{
/* 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_pes = NULL;
}
......@@ -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 */
/* 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 )
......@@ -273,7 +275,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
}
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_pes = NULL;
return;
......@@ -474,10 +476,11 @@ void input_GatherPES( input_thread_t * p_input, data_packet_t * p_data,
else
{
/* Update the relations between the data packets */
p_es->p_last->p_next = p_data;
p_pes->p_last->p_next = p_data;
}
p_es->p_last = p_data;
p_pes->p_last = p_data;
p_pes->i_nb_data++;
/* Size of the payload carried in the data packet */
p_pes->i_pes_size += (p_data->p_payload_end
......@@ -505,13 +508,13 @@ static u16 GetID( data_packet_t * p_data )
{
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 )
{
/* FIXME : this is not valid if the header is split in multiple
* packets */
/* 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 );
}
......@@ -530,14 +533,14 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
int i;
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" );
return;
}
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. */
return;
......@@ -545,12 +548,12 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
intf_DbgMsg( "Building PSM" );
p_demux->b_has_PSM = 1;
p_demux->i_PSM_version = p_data->p_payload_start[6] & 0x1F;
p_demux->i_PSM_version = p_data->p_demux_start[6] & 0x1F;
/* Go to elementary_stream_map_length, jumping over
* program_stream_info. */
p_byte = p_data->p_payload_start + 10
+ U16_AT(&p_data->p_payload_start[8]);
p_byte = p_data->p_demux_start + 10
+ U16_AT(&p_data->p_demux_start[8]);
if( p_byte > p_data->p_payload_end )
{
intf_ErrMsg( "PSM too short : packet corrupt" );
......@@ -655,7 +658,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
u32 i_code;
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 */
{
......@@ -694,7 +697,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
i_id, 0 );
if( p_es != NULL )
{
p_es->i_stream_id = p_data->p_payload_start[3];
p_es->i_stream_id = p_data->p_demux_start[3];
/* Set stream type and auto-spawn. */
if( (i_id & 0xF0) == 0xE0 )
......@@ -794,7 +797,10 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
boolean_t b_trash = 0;
es_descriptor_t * p_es = NULL;
i_code = U32_AT( p_data->p_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 )
{
switch( i_code )
......@@ -805,12 +811,12 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
mtime_t scr_time;
u32 i_mux_rate;
if( (p_data->p_payload_start[4] & 0xC0) == 0x40 )
if( (p_data->p_demux_start[4] & 0xC0) == 0x40 )
{
/* MPEG-2 */
byte_t p_header[14];
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 )
{
......@@ -841,7 +847,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
/* MPEG-1 SCR is like PTS. */
byte_t p_header[12];
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 )
{
......@@ -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;
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. */
i_pid = ((p[1] & 0x1F) << 8) | p[2];
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