The input-II. (more info by mail in about an hour)

This commit is contained in:
Christophe Massiot 2000-12-05 19:36:58 +00:00
parent d9cac7cd2a
commit dc804fe5e1
64 changed files with 2957 additions and 6788 deletions

View File

@ -100,7 +100,7 @@ ifeq ($(OPTIMS),1)
CFLAGS += -O6
CFLAGS += -ffast-math -funroll-loops -fargument-noalias-global
CFLAGS += -funroll-all-loops -fstrict-aliasing
CFLAGS += -fomit-frame-pointer
#CFLAGS += -fomit-frame-pointer
# Optimizations for x86 familiy
ifneq (,$(findstring 86,$(ARCH)))
@ -176,13 +176,9 @@ interface_obj = interface/main.o \
interface/intf_ctrl.o \
interface/intf_console.o
input_obj = input/input_vlan.o \
input/input_file.o \
input/input_netlist.o \
input/input_network.o \
input/input_ctrl.o \
input/input_pcr.o \
input/input_psi.o \
input_obj = input/input_ps.o \
input/mpeg_system.o \
input/input_ext-dec.o \
input/input.o
audio_output_obj = audio_output/audio_output.o
@ -236,8 +232,7 @@ misc_obj = misc/mtime.o \
misc/rsc_files.o \
misc/netutils.o \
misc/playlist.o \
misc/plugins.o \
misc/decoder_fifo.o
misc/plugins.o
C_OBJ = $(interface_obj) \

View File

@ -239,7 +239,7 @@
/* Duration between the time we receive the TS packet, and the time we will
* mark it to be presented */
#define INPUT_PTS_DELAY (.5*CLOCK_FREQ)
#define DEFAULT_PTS_DELAY (.5*CLOCK_FREQ)
#define INPUT_DVD_AUDIO_VAR "vlc_dvd_audio"
#define INPUT_DVD_CHANNEL_VAR "vlc_dvd_channel"

View File

@ -1,333 +0,0 @@
/*****************************************************************************
* decoder_fifo.h: interface for decoders PES fifo
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Required headers:
* - "config.h"
* - "common.h"
* - "threads.h"
* - "input.h"
*****************************************************************************/
#define WORD_TYPE u32
#define WORD_BYTE_LENGTH 4
#define WORD_LENGTH 32
/*****************************************************************************
* Macros
*****************************************************************************/
/* FIXME: move to inline functions ??*/
#define DECODER_FIFO_ISEMPTY( fifo ) ( (fifo).i_start == (fifo).i_end )
#define DECODER_FIFO_ISFULL( fifo ) ( ( ((fifo).i_end + 1 - (fifo).i_start)\
& FIFO_SIZE ) == 0 )
#define DECODER_FIFO_START( fifo ) ( (fifo).buffer[ (fifo).i_start ] )
#define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
& FIFO_SIZE )
#define DECODER_FIFO_END( fifo ) ( (fifo).buffer[ (fifo).i_end ] )
#define DECODER_FIFO_INCEND( fifo ) ( (fifo).i_end = ((fifo).i_end + 1) \
& FIFO_SIZE )
/*****************************************************************************
* decoder_fifo_t
*****************************************************************************
* This rotative FIFO contains PES packets that are to be decoded...
*****************************************************************************/
typedef struct
{
vlc_mutex_t data_lock; /* fifo data lock */
vlc_cond_t data_wait; /* fifo data conditional variable */
/* buffer is an array of PES packets pointers */
pes_packet_t * buffer[FIFO_SIZE + 1];
int i_start;
int i_end;
} decoder_fifo_t;
/*****************************************************************************
* bit_fifo_t : bit fifo descriptor
*****************************************************************************
* This type describes a bit fifo used to store bits while working with the
* input stream at the bit level.
*****************************************************************************/
typedef struct bit_fifo_s
{
/* This unsigned integer allows us to work at the bit level. This buffer
* can contain 32 bits, and the used space can be found on the MSb's side
* and the available space on the LSb's side. */
WORD_TYPE buffer;
/* Number of bits available in the bit buffer */
int i_available;
} bit_fifo_t;
/*****************************************************************************
* bit_stream_t : bit stream descriptor
*****************************************************************************
* This type, based on a PES stream, includes all the structures needed to
* handle the input stream like a bit stream.
*****************************************************************************/
typedef struct bit_stream_s
{
/*
* Input structures
*/
/* The input thread feeds the stream with fresh PES packets */
input_thread_t * p_input;
/* The decoder fifo contains the data of the PES stream */
decoder_fifo_t * p_decoder_fifo;
/*
* Byte structures
*/
/* Current TS packet (in the current PES packet of the PES stream) */
ts_packet_t * p_ts;
/* Pointer to the next byte that is to be read (in the current TS packet) */
byte_t * p_byte;
/* Pointer to the last byte that is to be read (in the current TS packet */
byte_t * p_end;
/*
* Bit structures
*/
bit_fifo_t fifo;
} bit_stream_t;
void decoder_fifo_next( bit_stream_t * p_bit_stream );
/*****************************************************************************
* GetByte : reads the next byte in the input stream
*****************************************************************************/
static __inline__ byte_t GetByte( bit_stream_t * p_bit_stream )
{
/* Are there some bytes left in the current TS packet ? */
/* could change this test to have a if (! (bytes--)) instead */
if ( p_bit_stream->p_byte >= p_bit_stream->p_end )
{
/* no, switch to next TS packet */
decoder_fifo_next( p_bit_stream );
}
return( *(p_bit_stream->p_byte++));
}
/*****************************************************************************
* NeedBits : reads i_bits new bits in the bit stream and stores them in the
* bit buffer
*****************************************************************************
* - i_bits must be less or equal 32 !
* - There is something important to notice with that function : if the number
* of bits available in the bit buffer when calling NeedBits() is greater than
* 24 (i_available > 24) but less than the number of needed bits
* (i_available < i_bits), the byte returned by GetByte() will be shifted with
* a negative value and the number of bits available in the bit buffer will be
* set to more than 32 !
*****************************************************************************/
static __inline__ void NeedBits( bit_stream_t * p_bit_stream, int i_bits )
{
while ( p_bit_stream->fifo.i_available < i_bits )
{
p_bit_stream->fifo.buffer |= ((u32)GetByte( p_bit_stream )) << (24 - p_bit_stream->fifo.i_available);
p_bit_stream->fifo.i_available += 8;
}
}
/*****************************************************************************
* DumpBits : removes i_bits bits from the bit buffer
*****************************************************************************
* - i_bits <= i_available
* - i_bits < 32 (because (u32 << 32) <=> (u32 = u32))
*****************************************************************************/
static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int i_bits )
{
p_bit_stream->fifo.buffer <<= i_bits;
p_bit_stream->fifo.i_available -= i_bits;
}
/*****************************************************************************
* DumpBits32 : removes 32 bits from the bit buffer
*****************************************************************************
* This function actually believes that you have already put 32 bits in the
* bit buffer, so you can't use it anytime.
*****************************************************************************/
static __inline__ void DumpBits32( bit_stream_t * p_bit_stream )
{
p_bit_stream->fifo.buffer = 0;
p_bit_stream->fifo.i_available = 0;
}
/*
* For the following functions, please read VERY CAREFULLY the warning in
* NeedBits(). If i_bits > 24, the stream parser must be already aligned
* on an 8-bit boundary, or you will get curious results (that is, you
* need to call RealignBits() before).
*/
void PeekNextPacket( bit_stream_t * p_bit_stream );
//(stolen from the kernel)
// XXX: The macro swab32 for little endian machine does
// not seem to work correctly
#if defined(SYS_BEOS)
# define swab32(x) B_BENDIAN_TO_HOST_INT32(x)
#else
# if __BYTE_ORDER == __BIG_ENDIAN
# define swab32(x) (x)
# else
# if defined (__i386__)
# define swab32(x) __i386_swab32(x)
static inline const u32 __i386_swab32(u32 x)
{
__asm__("bswap %0" : "=r" (x) : "0" (x));
return x;
}
# else
# define swab32(x)\
( ( (u32)(((u8*)&x)[0]) << 24 ) | ( (u32)(((u8*)&x)[1]) << 16 ) | \
( (u32)(((u8*)&x)[2]) << 8 ) | ( (u32)(((u8*)&x)[3])) )
# endif
# endif
#endif
static __inline__ WORD_TYPE GetWord( bit_stream_t * p_bit_stream )
{
if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
{
return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
}
else
{
PeekNextPacket( p_bit_stream );
return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
}
}
/*****************************************************************************
* RemoveBits : removes i_bits bits from the bit buffer
*****************************************************************************/
static __inline__ void RemoveBits( bit_stream_t * p_bit_stream, int i_bits )
{
p_bit_stream->fifo.i_available -= i_bits;
if( p_bit_stream->fifo.i_available >= 0 )
{
p_bit_stream->fifo.buffer <<= i_bits;
return;
}
p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
<< ( -p_bit_stream->fifo.i_available );
p_bit_stream->fifo.i_available += WORD_LENGTH;
}
/*****************************************************************************
* RemoveBits32 : removes 32 bits from the bit buffer (and as a side effect,
* refill it)
*****************************************************************************/
static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
{
p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
<< (32 - p_bit_stream->fifo.i_available);
}
/*****************************************************************************
* ShowBits : return i_bits bits from the bit stream
*****************************************************************************/
static __inline__ WORD_TYPE ShowWord( bit_stream_t * p_bit_stream )
{
if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
{
return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
}
PeekNextPacket( p_bit_stream );
return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
}
static __inline__ u32 ShowBits( bit_stream_t * p_bit_stream, int i_bits )
{
if( p_bit_stream->fifo.i_available >= i_bits )
{
return( p_bit_stream->fifo.buffer >> (32 - i_bits) );
}
return( (p_bit_stream->fifo.buffer |
(ShowWord( p_bit_stream ) >> p_bit_stream->fifo.i_available))
>> (32 - i_bits) );
}
/*****************************************************************************
* GetBits : returns i_bits bits from the bit stream and removes them
*****************************************************************************/
static __inline__ u32 GetBits( bit_stream_t * p_bit_stream, int i_bits )
{
u32 i_result;
p_bit_stream->fifo.i_available -= i_bits;
if( p_bit_stream->fifo.i_available >= 0 )
{
i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
p_bit_stream->fifo.buffer <<= i_bits;
return( i_result );
}
i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
i_result |= p_bit_stream->fifo.buffer
>> (32 + p_bit_stream->fifo.i_available);
p_bit_stream->fifo.buffer <<= ( -p_bit_stream->fifo.i_available );
p_bit_stream->fifo.i_available += WORD_LENGTH;
return( i_result );
}
/*****************************************************************************
* GetBits32 : returns 32 bits from the bit stream and removes them
*****************************************************************************/
static __inline__ u32 GetBits32( bit_stream_t * p_bit_stream )
{
u32 i_result;
i_result = p_bit_stream->fifo.buffer;
p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
i_result |= p_bit_stream->fifo.buffer
>> (p_bit_stream->fifo.i_available);
p_bit_stream->fifo.buffer <<= (32 - p_bit_stream->fifo.i_available);
return( i_result );
}
/*****************************************************************************
* RealignBits : realigns the bit buffer on an 8-bit boundary
*****************************************************************************/
static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
{
p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
p_bit_stream->fifo.i_available &= ~0x7;
}

View File

@ -1,385 +0,0 @@
/*****************************************************************************
* input.h: input thread interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
* Benoît Steiner <benny@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Constants related to input
*****************************************************************************/
#define TS_PACKET_SIZE 188 /* size of a TS packet */
#define PES_HEADER_SIZE 14 /* size of the first part of a PES header */
#define PSI_SECTION_SIZE 4096 /* Maximum size of a PSI section */
/*****************************************************************************
* ts_packet_t
*****************************************************************************
* Describe a TS packet.
*****************************************************************************/
typedef struct ts_packet_s
{
/* Nothing before this line, the code relies on that */
byte_t buffer[TS_PACKET_SIZE]; /* raw TS data packet */
/* Decoders information */
unsigned int i_payload_start;
/* start of the PES payload in this packet */
unsigned int i_payload_end; /* guess ? :-) */
/* Used to chain the TS packets that carry data for a same PES or PSI */
struct ts_packet_s * p_prev_ts;
struct ts_packet_s * p_next_ts;
} ts_packet_t;
/*****************************************************************************
* pes_packet_t
*****************************************************************************
* Describes an PES packet, with its properties, and pointers to the TS packets
* containing it.
*****************************************************************************/
typedef struct pes_packet_s
{
/* PES properties */
boolean_t b_data_loss; /* The previous (at least) PES packet
* has been lost. The decoders will have to find a way to recover. */
boolean_t b_data_alignment; /* used to find the beginning of
* a video or audio unit */
boolean_t b_has_pts; /* is the following field set ? */
mtime_t i_pts; /* the PTS for this packet (if set above) */
boolean_t b_random_access;
/* if TRUE, in the payload of this packet, there is the first byte
* of a video sequence header, or the first byte of an audio frame.
*/
u8 i_stream_id; /* payload type and id */
int i_pes_size; /* size of the current PES packet */
int i_pes_real_size; /* real size of the current
* PES packet, ie. the one
* announced in the header */
int i_ts_packets;/* number of TS packets in this PES */
/* Demultiplexer environment */
boolean_t b_discard_payload; /* is the packet messed up ? */
byte_t * p_pes_header; /* pointer to the PES header */
byte_t * p_pes_header_save; /* temporary buffer */
/* Pointers to TS packets (TS packets are then linked by the p_prev_ts and
p_next_ts fields of the ts_packet_t struct) */
ts_packet_t * p_first_ts; /* The first TS packet containing this
* PES (used by decoders). */
ts_packet_t * p_last_ts; /* The last TS packet gathered at present
* (used by the demultiplexer). */
} pes_packet_t;
/*****************************************************************************
* psi_section_t
*****************************************************************************
* Describes a PSI section. Beware, it doesn't contain pointers to the TS
* packets that contain it as for a PES, but the data themselves
*****************************************************************************/
typedef struct psi_section_s
{
byte_t buffer[PSI_SECTION_SIZE];
boolean_t b_running_section; /* Is there a section being decoded ? */
u16 i_length;
u16 i_current_position;
} psi_section_t;
/*****************************************************************************
* es_descriptor_t: elementary stream descriptor
*****************************************************************************
* Describes an elementary stream, and includes fields required to handle and
* demultiplex this elementary stream.
*****************************************************************************/
typedef struct es_descriptor_t
{
u16 i_id; /* stream ID, PID for TS streams */
u8 i_type; /* stream type */
boolean_t b_pcr; /* does the stream include a PCR ? */
/* XXX?? b_pcr will be replaced by something else: since a PCR can't be shared
* between several ES, we will probably store the PCR fields directly here,
* and one of those fields will probably (again) be used as a test of the
* PCR presence */
boolean_t b_psi; /* does the stream have to be handled by the
PSI decoder ? */
/* Markers */
int i_continuity_counter;
boolean_t b_discontinuity;
boolean_t b_random;
/* PES packets */
pes_packet_t * p_pes_packet;
/* current PES packet we are gathering */
/* PSI packets */
psi_section_t * p_psi_section; /* idem for a PSI stream */
/* Decoder informations */
void * p_dec; /* p_dec is void *, since we don't know a
* priori whether it is adec_thread_t or
* vdec_thread_t. We will use explicit
* casts. */
/* XXX?? video stream descriptor ? */
/* XXX?? audio stream descriptor ? */
/* XXX?? hierarchy descriptor ? */
/* XXX?? target background grid descriptor ? */
/* XXX?? video window descriptor ? */
/* XXX?? ISO 639 language descriptor ? */
#ifdef STATS
/* Stats */
count_t c_bytes; /* total bytes read */
count_t c_payload_bytes;/* total of payload useful bytes */
count_t c_packets; /* total packets read */
count_t c_invalid_packets; /* invalid packets read */
/* XXX?? ... other stats */
#endif
} es_descriptor_t;
/* Special PID values - note that the PID is only on 13 bits, and that values
* greater than 0x1fff have no meaning in a stream */
#define PROGRAM_ASSOCIATION_TABLE_PID 0x0000
#define CONDITIONNAL_ACCESS_TABLE_PID 0x0001 /* not used */
#define EMPTY_PID 0xffff /* empty record in a table */
/* ES streams types - see ISO/IEC 13818-1 table 2-29 numbers */
#define MPEG1_VIDEO_ES 0x01
#define MPEG2_VIDEO_ES 0x02
#define MPEG1_AUDIO_ES 0x03
#define MPEG2_AUDIO_ES 0x04
#define AC3_AUDIO_ES 0x81
#define DVD_SPU_ES 0x82 /* 0x82 might violate the norm */
#define LPCM_AUDIO_ES 0x83
/*****************************************************************************
* program_descriptor_t
*****************************************************************************
* Describes a program and list associated elementary streams. It is build by
* the PSI decoder upon the informations carried in program map sections
*****************************************************************************/
typedef struct
{
/* Program characteristics */
u16 i_number; /* program number */
u8 i_version; /* version number */
boolean_t b_is_ok; /* Is the description up to date ?*/
u16 i_pcr_pid; /* PCR ES */
int i_es_number;
es_descriptor_t ** ap_es; /* array of pointers to ES */
#ifdef DVB_EXTENSIONS
/* Service Descriptor (program name) */
u8 i_srv_type;
char* psz_srv_name;
#endif
/* XXX?? target background grid descriptor ? */
/* XXX?? video window descriptor ? */
/* XXX?? ISO 639 language descriptor ? */
#ifdef STATS
/* Stats */
/* XXX?? ...stats */
#endif
} pgrm_descriptor_t;
/*****************************************************************************
* pcr_descriptor_t
*****************************************************************************
* Contains informations used to synchronise the decoder with the server
*****************************************************************************/
typedef struct pcr_descriptor_struct
{
/* system_date = PTS_date + delta_pcr + delta_absolute */
mtime_t delta_pcr;
mtime_t delta_absolute;
mtime_t last_pcr;
u32 i_synchro_state;
count_t c_average_count;
/* counter used to compute dynamic average values */
} pcr_descriptor_t;
/*****************************************************************************
* stream_descriptor_t
*****************************************************************************
* Describes a transport stream and list its associated programs. Build upon
* the informations carried in program association sections
*****************************************************************************/
typedef struct
{
u16 i_stream_id; /* stream id */
/* Program Association Table status */
u8 i_PAT_version; /* version number */
boolean_t b_is_PAT_complete; /* Is the PAT complete ?*/
u8 i_known_PAT_sections;
/* Number of section we received so far */
byte_t a_known_PAT_sections[32];
/* Already received sections */
/* Program Map Table status */
boolean_t b_is_PMT_complete; /* Is the PMT complete ?*/
u8 i_known_PMT_sections;
/* Number of section we received so far */
byte_t a_known_PMT_sections[32];
/* Already received sections */
/* Service Description Table status */
u8 i_SDT_version; /* version number */
boolean_t b_is_SDT_complete; /* Is the SDT complete ?*/
u8 i_known_SDT_sections;
/* Number of section we received so far */
byte_t a_known_SDT_sections[32];
/* Already received sections */
/* Programs description */
int i_pgrm_number; /* Number of program number we have */
pgrm_descriptor_t ** ap_programs; /* Array of pointers to pgrm */
#ifdef STATS
/* Stats */
/* XXX?? ...stats */
#endif
} stream_descriptor_t;
/*****************************************************************************
* input_netlist_t
*****************************************************************************/
typedef struct
{
vlc_mutex_t lock; /* netlist modification lock */
struct iovec p_ts_free[INPUT_MAX_TS + INPUT_TS_READ_ONCE];
/* FIFO or LIFO of free TS packets */
ts_packet_t * p_ts_packets;
/* pointer to the first TS packet we allocated */
pes_packet_t * p_pes_free[INPUT_MAX_PES + 1];
/* FIFO or LIFO of free PES packets */
pes_packet_t * p_pes_packets;
/* pointer to the first PES packet we allocated */
/* To use the efficiency of the scatter/gather IO operations. We implemented
* it in 2 ways, as we don't know yet which one is better : as a FIFO (code
* simplier) or as a LIFO stack (when we doesn't care of the ordering, this
* allow to drastically improve the cache performance) */
#ifdef INPUT_LIFO_TS_NETLIST
int i_ts_index;
#else
int i_ts_start, i_ts_end;
#endif
#ifdef INPUT_LIFO_PES_NETLIST
int i_pes_index;
#else
int i_pes_start, i_pes_end;
#endif
} input_netlist_t;
/*****************************************************************************
* input_thread_t
*****************************************************************************
* This structure includes all the local static variables of an input thread,
* including the netlist and the ES descriptors
* Note that p_es must be defined as a static table, otherwise we would have to
* update all reference to it each time the table would be reallocated
*****************************************************************************/
/* Function pointers used in structure */
typedef int (input_open_t) ( p_input_thread_t p_input );
typedef int (input_read_t) ( p_input_thread_t p_input, const struct iovec *p_vector,
size_t i_count );
typedef void (input_close_t) ( p_input_thread_t p_input );
/* Structure */
typedef struct input_thread_s
{
/* Thread properties and locks */
boolean_t b_die; /* 'die' flag */
boolean_t b_error; /* deadlock */
vlc_thread_t thread_id; /* id for thread functions */
vlc_mutex_t programs_lock; /* programs modification lock */
vlc_mutex_t es_lock; /* es modification lock */
int * pi_status; /* temporary status flag */
/* Input method description */
int i_method; /* input method */
int i_handle; /* file/socket descriptor */
char * p_source; /* source */
int i_port; /* port number */
int i_vlan; /* id for vlan method */
input_open_t * p_Open; /* opener of the method */
input_read_t * p_Read; /* reading function */
input_close_t * p_Close; /* destroying function */
/* General stream description */
stream_descriptor_t * p_stream; /* PAT tables */
es_descriptor_t p_es[INPUT_MAX_ES];/* carried elementary streams */
pcr_descriptor_t * p_pcr; /* PCR struct used for synchronisation */
/* List of streams to demux */
es_descriptor_t * pp_selected_es[INPUT_MAX_SELECTED_ES];
/* Netlists */
input_netlist_t netlist; /* see above */
/* Default settings for spawned decoders */
p_aout_thread_t p_aout; /* audio output thread structure */
p_vout_thread_t p_vout; /* video output thread */
#ifdef STATS
/* Statistics */
count_t c_loops; /* number of loops */
count_t c_bytes; /* bytes read */
count_t c_payload_bytes; /* payload useful bytes */
count_t c_packets_read; /* packets read */
count_t c_packets_trashed; /* trashed packets */
#endif
} input_thread_t;
/* Input methods */
#define INPUT_METHOD_NONE 0 /* input thread is inactive */
#define INPUT_METHOD_TS_FILE 10 /* TS stream is read from a file */
#define INPUT_METHOD_TS_UCAST 20 /* TS UDP unicast */
#define INPUT_METHOD_TS_MCAST 21 /* TS UDP multicast */
#define INPUT_METHOD_TS_BCAST 22 /* TS UDP broadcast */
#define INPUT_METHOD_TS_VLAN_BCAST 32 /* TS UDP broadcast with VLANs */
/*****************************************************************************
* Prototypes
*****************************************************************************/
input_thread_t *input_CreateThread ( int i_method, void *p_source, int i_port,
int i_vlan, p_vout_thread_t p_vout,
p_aout_thread_t p_aout, int *pi_status );
void input_DestroyThread ( input_thread_t *p_input, int *pi_status );
int input_OpenAudioStream ( input_thread_t *p_input, int i_pid );
void input_CloseAudioStream ( input_thread_t *p_input, int i_pid );
int input_OpenVideoStream ( input_thread_t *p_input, int i_pid );
void input_CloseVideoStream ( input_thread_t *p_input, int i_pid );

459
include/input_ext-dec.h Normal file
View File

@ -0,0 +1,459 @@
/* Structures exported to the decoders */
/*****************************************************************************
* data_packet_t
*****************************************************************************
* Describe a data packet.
*****************************************************************************/
typedef struct data_packet_s
{
/* Nothing before this line, the code relies on that */
byte_t * p_buffer; /* raw data packet */
/* Decoders information */
byte_t * p_payload_start;
/* start of the PES payload in this packet */
byte_t * p_payload_end; /* guess ? :-) */
boolean_t b_discard_payload; /* is the packet messed up ? */
/* Used to chain the TS packets that carry data for a same PES or PSI */
struct data_packet_s * p_next;
} data_packet_t;
/*****************************************************************************
* pes_packet_t
*****************************************************************************
* Describes an PES packet, with its properties, and pointers to the TS packets
* containing it.
*****************************************************************************/
typedef struct pes_packet_s
{
/* PES properties */
boolean_t b_messed_up; /* At least one of the data packets
* has a questionable content */
boolean_t b_data_alignment; /* used to find the beginning of
* a video or audio unit */
boolean_t b_discontinuity; /* This packet doesn't follow the
* previous one */
boolean_t b_has_pts; /* is the following field set ? */
mtime_t i_pts; /* the PTS for this packet (if set above) */
int i_pes_size; /* size of the current PES packet */
/* Pointers to packets (packets are then linked by the p_prev and
p_next fields of the data_packet_t struct) */
data_packet_t * p_first; /* The first packet containing this
* PES (used by decoders). */
} pes_packet_t;
/*****************************************************************************
* decoder_fifo_t
*****************************************************************************
* This rotative FIFO contains PES packets that are to be decoded.
*****************************************************************************/
typedef struct decoder_fifo_s
{
/* Thread structures */
vlc_mutex_t data_lock; /* fifo data lock */
vlc_cond_t data_wait; /* fifo data conditional variable */
/* Data */
pes_packet_t * buffer[FIFO_SIZE + 1];
int i_start;
int i_end;
/* Communication interface between input and decoders */
boolean_t b_die; /* the decoder should return now */
void * p_packets_mgt; /* packets management services
* data (netlist...) */
void (* pf_delete_pes)( void *, pes_packet_t * );
/* function to use when releasing a PES */
} decoder_fifo_t;
/* Macros to manage a decoder_fifo_t structure. Please remember to take
* data_lock before using them. */
#define DECODER_FIFO_ISEMPTY( fifo ) ( (fifo).i_start == (fifo).i_end )
#define DECODER_FIFO_ISFULL( fifo ) ( ( ((fifo).i_end + 1 - (fifo).i_start)\
& FIFO_SIZE ) == 0 )
#define DECODER_FIFO_START( fifo ) ( (fifo).buffer[ (fifo).i_start ] )
#define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
& FIFO_SIZE )
#define DECODER_FIFO_END( fifo ) ( (fifo).buffer[ (fifo).i_end ] )
#define DECODER_FIFO_INCEND( fifo ) ( (fifo).i_end = ((fifo).i_end + 1) \
& FIFO_SIZE )
/*****************************************************************************
* bit_fifo_t : bit fifo descriptor
*****************************************************************************
* This type describes a bit fifo used to store bits while working with the
* input stream at the bit level.
*****************************************************************************/
typedef u32 WORD_TYPE; /* only u32 is supported at the moment */
typedef struct bit_fifo_s
{
/* This unsigned integer allows us to work at the bit level. This buffer
* can contain 32 bits, and the used space can be found on the MSb's side
* and the available space on the LSb's side. */
WORD_TYPE buffer;
/* Number of bits available in the bit buffer */
int i_available;
} bit_fifo_t;
/*****************************************************************************
* bit_stream_t : bit stream descriptor
*****************************************************************************
* This type, based on a PES stream, includes all the structures needed to
* handle the input stream like a bit stream.
*****************************************************************************/
typedef struct bit_stream_s
{
/*
* Input structures
*/
/* The decoder fifo contains the data of the PES stream */
decoder_fifo_t * p_decoder_fifo;
/* Function to jump to the next data packet */
void (* pf_next_data_packet)( struct bit_stream_s * );
/*
* Byte structures
*/
/* Current data packet (in the current PES packet of the PES stream) */
data_packet_t * p_data;
/* Pointer to the next byte that is to be read (in the current TS packet) */
byte_t * p_byte;
/* Pointer to the last byte that is to be read (in the current TS packet */
byte_t * p_end;
/*
* Bit structures
*/
bit_fifo_t fifo;
} bit_stream_t;
/*****************************************************************************
* Inline functions used by the decoders to read bit_stream_t
*****************************************************************************/
/*
* Philosophy of the first implementation : the bit buffer is first filled by
* NeedBits, then the buffer can be read via p_bit_stream->fifo.buffer, and
* unnecessary bits are dumped with a DumpBits() call.
*/
/*****************************************************************************
* GetByte : reads the next byte in the input stream
*****************************************************************************/
static __inline__ byte_t GetByte( bit_stream_t * p_bit_stream )
{
/* Are there some bytes left in the current data packet ? */
/* could change this test to have a if (! (bytes--)) instead */
if ( p_bit_stream->p_byte >= p_bit_stream->p_end )
{
/* no, switch to next data packet */
p_bit_stream->pf_next_data_packet( p_bit_stream );
}
return( *(p_bit_stream->p_byte++) );
}
/*****************************************************************************
* NeedBits : reads i_bits new bits in the bit stream and stores them in the
* bit buffer
*****************************************************************************
* - i_bits must be less or equal 32 !
* - There is something important to notice with that function : if the number
* of bits available in the bit buffer when calling NeedBits() is greater than
* 24 (i_available > 24) but less than the number of needed bits
* (i_available < i_bits), the byte returned by GetByte() will be shifted with
* a negative value and the number of bits available in the bit buffer will be
* set to more than 32 !
*****************************************************************************/
static __inline__ void NeedBits( bit_stream_t * p_bit_stream, int i_bits )
{
while ( p_bit_stream->fifo.i_available < i_bits )
{
p_bit_stream->fifo.buffer |= ((WORD_TYPE)GetByte( p_bit_stream ))
<< (sizeof(WORD_TYPE) - 8
- p_bit_stream->fifo.i_available);
p_bit_stream->fifo.i_available += 8;
}
}
/*****************************************************************************
* DumpBits : removes i_bits bits from the bit buffer
*****************************************************************************
* - i_bits <= i_available
* - i_bits < 32 (because (u32 << 32) <=> (u32 = u32))
*****************************************************************************/
static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int i_bits )
{
p_bit_stream->fifo.buffer <<= i_bits;
p_bit_stream->fifo.i_available -= i_bits;
}
/*
* Philosophy of the second implementation : WORD_LENGTH (usually 32) bits
* are read at the same time, thus minimizing the number of p_byte changes.
* Bits are read via GetBits() or ShowBits. This is slightly faster. Be
* aware that if, in the forthcoming functions, i_bits > 24, the data have to
* be already aligned on an 8-bit boundary, or wrong results will be
* returned.
*/
#if (WORD_TYPE != u32)
# error Not supported word
#endif
/*
* This is stolen from the livid source who stole it from the kernel
* FIXME: The macro swab32 for little endian machines does
* not seem to work correctly
*/
#if defined(SYS_BEOS)
# define swab32(x) B_BENDIAN_TO_HOST_INT32(x)
#else
# if __BYTE_ORDER == __BIG_ENDIAN
# define swab32(x) (x)
# else
# if defined (__i386__)
static __inline__ const u32 __i386_swab32( u32 x )
{
__asm__("bswap %0" : "=r" (x) : "0" (x));
return x;
}
# define swab32(x) __i386_swab32(x)
# else
# define swab32(x) \
( ( (u32)(((u8*)&x)[0]) << 24 ) | ( (u32)(((u8*)&x)[1]) << 16 ) |\
( (u32)(((u8*)&x)[2]) << 8 ) | ( (u32)(((u8*)&x)[3])) )
# endif
# endif
#endif
/*****************************************************************************
* ShowBits : return i_bits bits from the bit stream
*****************************************************************************/
static __inline__ WORD_TYPE ShowWord( bit_stream_t * p_bit_stream )
{
if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
{
return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
}
p_bit_stream->pf_next_data_packet( p_bit_stream );
return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
}
static __inline__ WORD_TYPE ShowBits( bit_stream_t * p_bit_stream, int i_bits )
{
if( p_bit_stream->fifo.i_available >= i_bits )
{
return( p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - i_bits) );
}
return( (p_bit_stream->fifo.buffer |
(ShowWord( p_bit_stream ) >> p_bit_stream->fifo.i_available))
>> (8 * sizeof(WORD_TYPE) - i_bits) );
}
/*****************************************************************************
* GetWord : returns the next word to be read
*****************************************************************************/
static __inline__ WORD_TYPE GetWord( bit_stream_t * p_bit_stream )
{
if( p_bit_stream->p_byte <= p_bit_stream->p_end - sizeof(WORD_TYPE) )
{
return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
}
else
{
p_bit_stream->pf_next_data_packet( p_bit_stream );
return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
}
}
/*****************************************************************************
* RemoveBits : removes i_bits bits from the bit buffer
*****************************************************************************/
static __inline__ void RemoveBits( bit_stream_t * p_bit_stream, int i_bits )
{
p_bit_stream->fifo.i_available -= i_bits;
if( p_bit_stream->fifo.i_available >= 0 )
{
p_bit_stream->fifo.buffer <<= i_bits;
return;
}
p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
<< ( -p_bit_stream->fifo.i_available );
p_bit_stream->fifo.i_available += sizeof(WORD_TYPE) * 8;
}
/*****************************************************************************
* RemoveBits32 : removes 32 bits from the bit buffer (and as a side effect,
* refill it). This should be faster than RemoveBits, though
* RemoveBits will work, too.
*****************************************************************************/
static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
{
p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
<< (32 - p_bit_stream->fifo.i_available);
}
/*****************************************************************************
* GetBits : returns i_bits bits from the bit stream and removes them
*****************************************************************************/
static __inline__ WORD_TYPE GetBits( bit_stream_t * p_bit_stream, int i_bits )
{
u32 i_result;
p_bit_stream->fifo.i_available -= i_bits;
if( p_bit_stream->fifo.i_available >= 0 )
{
i_result = p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - i_bits);
p_bit_stream->fifo.buffer <<= i_bits;
return( i_result );
}
i_result = p_bit_stream->fifo.buffer >> (8 * sizeof(WORD_TYPE) - i_bits);
p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
i_result |= p_bit_stream->fifo.buffer
>> (8 * sizeof(WORD_TYPE)
+ p_bit_stream->fifo.i_available);
p_bit_stream->fifo.buffer <<= ( -p_bit_stream->fifo.i_available );
p_bit_stream->fifo.i_available += sizeof(WORD_TYPE) * 8;
return( i_result );
}
/*****************************************************************************
* GetBits32 : returns 32 bits from the bit stream and removes them
*****************************************************************************/
static __inline__ WORD_TYPE GetBits32( bit_stream_t * p_bit_stream )
{
WORD_TYPE i_result;
i_result = p_bit_stream->fifo.buffer;
p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
i_result |= p_bit_stream->fifo.buffer
>> (p_bit_stream->fifo.i_available);
p_bit_stream->fifo.buffer <<= (8 * sizeof(WORD_TYPE)
- p_bit_stream->fifo.i_available);
return( i_result );
}
/*****************************************************************************
* RealignBits : realigns the bit buffer on an 8-bit boundary
*****************************************************************************/
static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
{
p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
p_bit_stream->fifo.i_available &= ~0x7;
}
/*
* Communication interface between input and decoders
*/
/*****************************************************************************
* decoder_config_t
*****************************************************************************
* Standard pointers given to the decoders as a toolbox.
*****************************************************************************/
typedef struct decoder_config_s
{
u16 i_stream_id;
u8 i_type; /* type of the elementary stream */
struct stream_ctrl_s * p_stream_ctrl;
struct decoder_fifo_s * p_decoder_fifo;
void (* pf_init_bit_stream)( struct bit_stream_s *,
struct decoder_fifo_s * );
} decoder_config_t;
/*****************************************************************************
* vdec_config_t
*****************************************************************************
* Pointers given to video decoders threads.
*****************************************************************************/
struct vout_thread_s;
typedef struct vdec_config_s
{
struct vout_thread_s * p_vout;
struct picture_s * (* pf_create_picture)( struct vout_thread_s *,
int i_type, int i_width,
int i_height );
void (* pf_destroy_picture)( struct vout_thread_s *,
struct picture_s * );
void (* pf_display_picture)( struct vout_thread_s *,
struct picture_s * );
void (* pf_date_picture)( struct vout_thread_s *,
struct picture_s *, mtime_t date );
void (* pf_link_picture)( struct vout_thread_s *,
struct picture_s *, mtime_t date );
void (* pf_unlink_picture)( struct vout_thread_s *,
struct picture_s *, mtime_t date );
struct subpicture_s *(* pf_create_subpicture)( struct vout_thread_s *,
int i_type, int i_size );
void (* pf_destroy_subpicture)( struct vout_thread_s *,
struct subpicture_s * );
void (* pf_display_subpicture)( struct vout_thread_s *,
struct subpicture_s * );
decoder_config_t decoder_config;
} vdec_config_t;
/*****************************************************************************
* adec_config_t
*****************************************************************************
* Pointers given to audio decoders threads.
*****************************************************************************/
struct aout_thread_s;
typedef struct adec_config_s
{
struct aout_thread_s * p_aout;
struct aout_fifo_s * (* pf_create_fifo)( struct aout_thread_s *,
struct aout_fifo_s * );
void (* pf_destroy_fifo)( struct aout_thread_s *);
decoder_config_t decoder_config;
} adec_config_t;
/*
* Communication interface between decoders and input
*/
/*****************************************************************************
* decoder_capabilities_t
*****************************************************************************
* Structure returned by a call to GetCapabilities() of the decoder.
*****************************************************************************/
typedef struct decoder_capabilities_s
{
int i_dec_type;
u8 i_stream_type; /* == i_type in es_descriptor_t */
int i_weight; /* for a given stream type, the decoder
* with higher weight will be spawned */
vlc_thread_t (* pf_create_thread)( struct decoder_config_s * );
} decoder_capabilities_t;
/* Decoder types */
#define NONE_D 0
#define VIDEO_D 1
#define AUDIO_D 2

246
include/input_ext-intf.h Normal file
View File

@ -0,0 +1,246 @@
/* Structures exported to the interface */
/*
* Communication input -> interface
*/
#define INPUT_MAX_PLUGINS 1
/*****************************************************************************
* es_descriptor_t: elementary stream descriptor
*****************************************************************************
* Describes an elementary stream, and includes fields required to handle and
* demultiplex this elementary stream.
*****************************************************************************/
struct decoder_fifo_s; /* defined in input_ext-dec.h */
struct pgrm_descriptor_s;
typedef struct es_descriptor_s
{
u16 i_id; /* stream ID for PS, PID for TS */
u8 i_stream_id; /* stream ID defined in the PES */
u8 i_type; /* stream type */
/* Demultiplexer information */
void * p_demux_data;
struct pgrm_descriptor_s *
p_pgrm; /* very convenient in the demultiplexer */
boolean_t b_discontinuity;
/* PES parser information */
struct pes_packet_s * p_pes; /* Current PES */
struct data_packet_s * p_last; /* The last packet gathered at present */
int i_pes_real_size; /* as indicated by the header */
/* Decoder information */
struct decoder_fifo_s * p_decoder_fifo;
vlc_thread_t thread_id; /* ID of the decoder */
#ifdef STATS
count_t c_payload_bytes;/* total of payload useful bytes */
count_t c_packets; /* total packets read */
count_t c_invalid_packets; /* invalid packets read */
#endif
} es_descriptor_t;
/* Special PID values - note that the PID is only on 13 bits, and that values
* greater than 0x1fff have no meaning in a stream */
#define PROGRAM_ASSOCIATION_TABLE_PID 0x0000
#define CONDITIONNAL_ACCESS_TABLE_PID 0x0001 /* not used */
#define EMPTY_ID 0xffff /* empty record in a table */
/* ES streams types - see ISO/IEC 13818-1 table 2-29 numbers */
#define MPEG1_VIDEO_ES 0x01
#define MPEG2_VIDEO_ES 0x02
#define MPEG1_AUDIO_ES 0x03
#define MPEG2_AUDIO_ES 0x04
#define AC3_AUDIO_ES 0x81
#define DVD_SPU_ES 0x82 /* 0x82 might violate the norm */
#define LPCM_AUDIO_ES 0x83
/*****************************************************************************
* pgrm_descriptor_t
*****************************************************************************
* Describes a program and list associated elementary streams. It is build by
* the PSI decoder upon the informations carried in program map sections
*****************************************************************************/
typedef struct pgrm_descriptor_s
{
/* Program characteristics */
u16 i_number; /* program number */
u8 i_version; /* version number */
boolean_t b_is_ok; /* Is the description up to date ? */
/* Service Descriptor (program name) - DVB extension */
u8 i_srv_type;
char * psz_srv_name;
/* Synchronization information */
/* system_date = PTS_date + delta_cr + delta_absolute */
mtime_t delta_cr;
mtime_t delta_absolute;
mtime_t last_cr;
count_t c_average_count;
/* counter used to compute dynamic average values */
int i_synchro_state;
/* Demultiplexer data */
void * p_demux_data;
/* Decoders control */
struct vout_thread_s * p_vout;
struct aout_thread_s * p_aout;
int i_es_number; /* size of the following array */
es_descriptor_t ** pp_es; /* array of pointers to ES */
} pgrm_descriptor_t;
/* Synchro states */
#define SYNCHRO_OK 0
#define SYNCHRO_NOT_STARTED 1
#define SYNCHRO_START 2
#define SYNCHRO_REINIT 3
/*****************************************************************************
* stream_descriptor_t
*****************************************************************************
* Describes a stream and list its associated programs. Build upon
* the information carried in program association sections (for instance)
*****************************************************************************/
typedef struct stream_descriptor_s
{
u16 i_stream_id; /* stream id */
vlc_mutex_t stream_lock; /* to be taken every time you read
* or modify stream, pgrm or es */
/* Input method data */
boolean_t b_pace_control; /* can we read when we want ? */
boolean_t b_seekable; /* can we do lseek() ? */
/* if (b_seekable) : */
off_t i_size; /* total size of the file (in bytes) */
off_t i_tell;/* actual location in the file (in bytes) */
/* Demultiplexer data */
void * p_demux_data;
/* Programs description */
int i_pgrm_number; /* size of the following array */
pgrm_descriptor_t ** pp_programs; /* array of pointers to pgrm */
/* Stream control */
stream_ctrl_t control;
} stream_descriptor_t;
/*****************************************************************************
* i_p_config_t
*****************************************************************************
* This structure gives plugins pointers to the useful functions of input
*****************************************************************************/
struct input_thread_s;
struct data_packet_s;
struct es_descriptor_s;
typedef struct i_p_config_s
{
int (* pf_peek_stream)( struct input_thread_s *,
byte_t * buffer, size_t );
void (* pf_demux_pes)( struct input_thread_s *,
struct data_packet_s *,
struct es_descriptor_s *,
boolean_t b_unit_start,
boolean_t b_packet_lost );
} i_p_config_t;
/*****************************************************************************
* input_thread_t
*****************************************************************************
* This structure includes all the local static variables of an input thread
*****************************************************************************/
struct aout_thread_s;
struct vout_thread_s;
typedef struct input_thread_s
{
/* Thread properties and locks */
boolean_t b_die; /* 'die' flag */
boolean_t b_error;
vlc_thread_t thread_id; /* id for thread functions */
int * pi_status; /* temporary status flag */
struct input_config_s * p_config;
struct input_capabilities_s *
pp_plugins[INPUT_MAX_PLUGINS];/* list of plugins */
struct input_capabilities_s *
p_plugin; /* selected plugin */
i_p_config_t i_p_config; /* plugin configuration */
int i_handle; /* socket or file descriptor */
void * p_method_data;
/* General stream description */
stream_descriptor_t stream; /* PAT tables */
es_descriptor_t p_es[INPUT_MAX_ES];
/* carried elementary streams */
/* List of streams to demux */
es_descriptor_t * pp_selected_es[INPUT_MAX_SELECTED_ES];
/* For auto-launch of decoders */
struct aout_thread_s * p_default_aout;
struct vout_thread_s * p_default_vout;
#ifdef STATS
count_t c_loops;
count_t c_bytes; /* bytes read */
count_t c_payload_bytes; /* payload useful bytes */
count_t c_packets_read; /* packets read */
count_t c_packets_trashed; /* trashed packets */
#endif
} input_thread_t;
/*
* Communication interface -> input
*/
/*****************************************************************************
* input_config_t
*****************************************************************************
* This structure is given by the interface to an input thread
*****************************************************************************/
typedef struct input_config_s
{
/* Input method description */
int i_method; /* input method */
char * p_source; /* source */
/* For auto-launch of decoders */
struct aout_thread_s * p_default_aout;
struct vout_thread_s * p_default_vout;
} input_config_t;
/* Input methods */
#define INPUT_METHOD_NONE 0 /* input thread is inactive */
#define INPUT_METHOD_FILE 10 /* stream is read from file p_source */
#define INPUT_METHOD_UCAST 20 /* UDP unicast */
#define INPUT_METHOD_MCAST 21 /* UDP multicast */
#define INPUT_METHOD_BCAST 22 /* UDP broadcast */
#define INPUT_METHOD_VLAN_BCAST 32 /* UDP broadcast with VLANs */
/*****************************************************************************
* Prototypes
*****************************************************************************/
struct input_thread_s * input_CreateThread( struct input_config_s *,
int *pi_status );
void input_DestroyThread( struct input_thread_s *,
int *pi_status );
void input_PauseProgram( struct input_thread_s *,
struct pgrm_descriptor_s * );
void input_PlayProgram( struct input_thread_s *,
struct pgrm_descriptor_s * );
void input_FFProgram( struct input_thread_s *,
struct pgrm_descriptor_s * );
void input_SMProgram( struct input_thread_s *,
struct pgrm_descriptor_s * );
void input_RewindProgram( struct input_thread_s *,
struct pgrm_descriptor_s * );

View File

@ -1,174 +0,0 @@
/*****************************************************************************
* input_netlist.h: netlist interface
* The netlists are an essential part of the input structure. We maintain a
* list of free TS packets and free PES packets to avoid continuous malloc
* and free.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include "intf_msg.h"
/*****************************************************************************
* Prototypes
*****************************************************************************/
int input_NetlistInit ( input_thread_t *p_input );
void input_NetlistEnd ( input_thread_t *p_input );
static __inline__ void input_NetlistFreePES( input_thread_t *p_input, pes_packet_t *p_pes_packet );
static __inline__ void input_NetlistFreeTS( input_thread_t *p_input, ts_packet_t *p_ts_packet );
static __inline__ pes_packet_t* input_NetlistGetPES( input_thread_t *p_input );
/*****************************************************************************
* input_NetlistFreePES: add a PES packet to the netlist
*****************************************************************************
* Add a PES packet to the PES netlist, so that the packet can immediately be
* reused by the demultiplexer. We put this function directly in the .h file,
* because it is very frequently called.
*****************************************************************************/
static __inline__ void input_NetlistFreePES( input_thread_t *p_input,
pes_packet_t *p_pes_packet )
{
int i_dummy;
ts_packet_t * p_ts_packet;
ASSERT(p_pes_packet);
/* We will be playing with indexes, so we take a lock. */
vlc_mutex_lock( &p_input->netlist.lock );
/* Free all TS packets in this PES structure. */
p_ts_packet = p_pes_packet->p_first_ts;
for( i_dummy = 0; i_dummy < p_pes_packet->i_ts_packets; i_dummy++ )
{
ASSERT(p_ts_packet);
#ifdef INPUT_LIFO_TS_NETLIST
p_input->netlist.i_ts_index--;
p_input->netlist.p_ts_free[p_input->netlist.i_ts_index].iov_base
= (void *)p_ts_packet;
#else /* FIFO */
p_input->netlist.p_ts_free[p_input->netlist.i_ts_end].iov_base
= (void *)p_ts_packet;
p_input->netlist.i_ts_end++;
p_input->netlist.i_ts_end &= INPUT_MAX_TS; /* loop */
#endif
p_ts_packet = p_ts_packet->p_next_ts;
}
/* Free the PES structure. */
#ifdef INPUT_LIFO_PES_NETLIST
p_input->netlist.i_pes_index--;
p_input->netlist.p_pes_free[p_input->netlist.i_pes_index] = p_pes_packet;
#else /* FIFO */
p_input->netlist.p_pes_free[p_input->netlist.i_pes_end] = p_pes_packet;
p_input->netlist.i_pes_end++;
p_input->netlist.i_pes_end &= INPUT_MAX_PES; /* loop */
#endif
vlc_mutex_unlock( &p_input->netlist.lock );
}
/*****************************************************************************
* input_NetlistFreeTS: add a TS packet to the netlist
*****************************************************************************
* Add a TS packet to the TS netlist, so that the packet can immediately be
* reused by the demultiplexer. Shouldn't be called by other threads (they
* should only use input_FreePES.
*****************************************************************************/
static __inline__ void input_NetlistFreeTS( input_thread_t *p_input,
ts_packet_t *p_ts_packet )
{
ASSERT(p_ts_packet);
/* We will be playing with indexes, so we take a lock. */
vlc_mutex_lock( &p_input->netlist.lock );
/* Free the TS structure. */
#ifdef INPUT_LIFO_TS_NETLIST
p_input->netlist.i_ts_index--;
p_input->netlist.p_ts_free[p_input->netlist.i_ts_index].iov_base
= (void *)p_ts_packet;
#else /* FIFO */
p_input->netlist.p_ts_free[p_input->netlist.i_ts_end].iov_base
= (void *)p_ts_packet;
p_input->netlist.i_ts_end++;
p_input->netlist.i_ts_end &= INPUT_MAX_TS; /* loop */
#endif
vlc_mutex_unlock( &p_input->netlist.lock );
}
/*****************************************************************************
* input_NetlistGetPES: remove a PES packet from the netlist
*****************************************************************************
* Add a TS packet to the TS netlist, so that the packet can immediately be
* reused by the demultiplexer. Shouldn't be called by other threads (they
* should only use input_FreePES.
*****************************************************************************/
static __inline__ pes_packet_t* input_NetlistGetPES( input_thread_t *p_input )
{
pes_packet_t * p_pes_packet;
#ifdef INPUT_LIFO_PES_NETLIST
/* i_pes_index might be accessed by a decoder thread to give back a
* packet. */
vlc_mutex_lock( &p_input->netlist.lock );
/* Verify that we still have PES packet in the netlist */
if( (INPUT_MAX_PES - p_input->netlist.i_pes_index ) <= 1 )
{
intf_ErrMsg("input error: PES netlist is empty !\n");
return( NULL );
}
/* Fetch a new PES packet */
p_pes_packet = p_input->netlist.p_pes_free[p_input->netlist.i_pes_index];
p_input->netlist.i_pes_index++;
vlc_mutex_unlock( &p_input->netlist.lock );
#else /* FIFO */
/* No need to lock, since we are the only ones accessing i_pes_start. */
/* Verify that we still have PES packet in the netlist */
if( ((p_input->netlist.i_pes_end -1 - p_input->netlist.i_pes_start) & INPUT_MAX_PES) <= 1 )
{
intf_ErrMsg("input error: PES netlist is empty !\n");
return( NULL );
}
p_pes_packet = p_input->netlist.p_pes_free[p_input->netlist.i_pes_start];
p_input->netlist.i_pes_start++;
p_input->netlist.i_pes_start &= INPUT_MAX_PES; /* loop */
#endif /* netlist type */
/* Initialize PES flags. */
p_pes_packet->b_data_loss = 0;
p_pes_packet->b_data_alignment = 0;
p_pes_packet->b_has_pts = 0;
p_pes_packet->b_random_access = 0;
p_pes_packet->b_discard_payload = 0;
p_pes_packet->i_pes_size = 0;
p_pes_packet->i_pes_real_size = 0;
p_pes_packet->i_ts_packets = 0;
p_pes_packet->p_first_ts = NULL;
p_pes_packet->p_last_ts = NULL;
return( p_pes_packet );
}

View File

@ -1,32 +0,0 @@
/*****************************************************************************
* input_file.h: file input method
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Prototypes
*****************************************************************************/
#define REQUESTED_AC3 0
#define REQUESTED_MPEG 1
#define REQUESTED_LPCM 2
#define REQUESTED_NOAUDIO 255

28
include/stream_control.h Normal file
View File

@ -0,0 +1,28 @@
/* Structures exported to interface, input and decoders */
/*****************************************************************************
* stream_ctrl_t
*****************************************************************************
* Describe the state of a program stream.
*****************************************************************************/
typedef struct stream_ctrl_s
{
vlc_mutex_t control_lock;
int i_status;
/* if i_status == FORWARD_S or BACKWARD_S */
int i_rate;
s64 i_ref_sysdate;
s64 i_ref_clock;
boolean_t b_mute;
boolean_t b_bw; /* black & white */
} stream_ctrl_t;
/* Possible status : */
#define PLAYING_S 0
#define PAUSE_S 1
#define FORWARD_S 2
#define BACKWARD_S 3
#define DEFAULT_RATE 1000

View File

@ -95,10 +95,10 @@ typedef struct vpar_thread_s
/* Input properties */
decoder_fifo_t fifo; /* PES input fifo */
/* The bit stream structure handles the PES stream at the bit level */
decoder_fifo_t * p_fifo; /* PES input fifo */
bit_stream_t bit_stream;
vdec_config_t * p_config;
/* Output properties */
vout_thread_t * p_vout; /* video output thread */
@ -151,28 +151,20 @@ typedef struct vpar_thread_s
*****************************************************************************/
/* Thread management functions */
vpar_thread_t * vpar_CreateThread ( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
vout_thread_t *p_vout, int *pi_status */ );
void vpar_DestroyThread ( vpar_thread_t *p_vpar /*, int *pi_status */ );
/* Time management functions */
/* XXX?? */
/* Dynamic thread settings */
/* XXX?? */
vlc_thread_t vpar_CreateThread ( vdec_config_t * );
/*****************************************************************************
* NextStartCode : Find the next start code
*****************************************************************************/
static __inline__ void NextStartCode( vpar_thread_t * p_vpar )
static __inline__ void NextStartCode( bit_stream_t * p_bit_stream )
{
/* Re-align the buffer on an 8-bit boundary */
RealignBits( &p_vpar->bit_stream );
RealignBits( p_bit_stream );
while( ShowBits( &p_vpar->bit_stream, 24 ) != 0x01L && !p_vpar->b_die )
while( ShowBits( p_bit_stream, 24 ) != 0x01L
&& !p_bit_stream->p_decoder_fifo->b_die )
{
RemoveBits( &p_vpar->bit_stream, 8 );
RemoveBits( p_bit_stream, 8 );
}
}

View File

@ -26,8 +26,6 @@
#include "defs.h"
#include <stdlib.h> /* malloc(), free() */
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* "input.h" */
#include "config.h"
#include "common.h"
@ -35,7 +33,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -44,7 +44,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -42,7 +42,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -36,7 +36,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -41,7 +41,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -41,7 +41,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -38,7 +38,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -41,7 +41,9 @@
#include "mtime.h"
#include "plugins.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"

View File

@ -50,9 +50,8 @@
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "input.h" /* pes_packet_t */
#include "input_netlist.h" /* input_NetlistFreePES() */
#include "decoder_fifo.h" /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
#include "stream_control.h"
#include "input_ext-dec.h"
#include "audio_output.h"
@ -72,7 +71,7 @@ static void EndThread (ac3dec_thread_t * p_adec);
/*****************************************************************************
* ac3dec_CreateThread: creates an ac3 decoder thread
*****************************************************************************/
ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
{
ac3dec_thread_t * p_ac3dec;
@ -83,7 +82,7 @@ ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
{
intf_ErrMsg ( "ac3dec error: not enough memory "
"for ac3dec_CreateThread() to create the new thread\n");
return NULL;
return 0;
}
/*
@ -91,27 +90,16 @@ ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
*/
p_ac3dec->b_die = 0;
p_ac3dec->b_error = 0;
/*
* Initialize the input properties
*/
/* Initialize the decoder fifo's data lock and conditional variable and set
* its buffer as empty */
vlc_mutex_init (&p_ac3dec->fifo.data_lock);
vlc_cond_init (&p_ac3dec->fifo.data_wait);
p_ac3dec->fifo.i_start = 0;
p_ac3dec->fifo.i_end = 0;
p_ac3dec->p_config = p_config;
p_ac3dec->p_fifo = p_config->decoder_config.p_decoder_fifo;
/* Initialize the ac3 decoder structures */
ac3_init (&p_ac3dec->ac3_decoder);
/* Initialize the bit stream structure */
p_ac3dec->p_input = p_input;
/*
* Initialize the output properties
*/
p_ac3dec->p_aout = p_input->p_aout;
p_ac3dec->p_aout = p_config->p_aout;
p_ac3dec->p_aout_fifo = NULL;
/* Spawn the ac3 decoder thread */
@ -119,31 +107,11 @@ ac3dec_thread_t * ac3dec_CreateThread (input_thread_t * p_input)
{
intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread\n" );
free (p_ac3dec);
return NULL;
return 0;
}
intf_DbgMsg ("ac3dec debug: ac3 decoder thread (%p) created\n", p_ac3dec);
return p_ac3dec;
}
/*****************************************************************************
* ac3dec_DestroyThread: destroys an ac3 decoder thread
*****************************************************************************/
void ac3dec_DestroyThread (ac3dec_thread_t * p_ac3dec)
{
intf_DbgMsg ("ac3dec debug: requesting termination of ac3 decoder thread %p\n", p_ac3dec);
/* Ask thread to kill itself */
p_ac3dec->b_die = 1;
/* Make sure the decoder thread leaves the GetByte() function */
vlc_mutex_lock (&(p_ac3dec->fifo.data_lock));
vlc_cond_signal (&(p_ac3dec->fifo.data_wait));
vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join (p_ac3dec->thread_id);
return p_ac3dec->thread_id;
}
/* Following functions are local */
@ -158,26 +126,12 @@ static int InitThread (ac3dec_thread_t * p_ac3dec)
intf_DbgMsg ("ac3dec debug: initializing ac3 decoder thread %p\n", p_ac3dec);
/* Our first job is to initialize the bit stream structure with the
* beginning of the input stream */
vlc_mutex_lock (&p_ac3dec->fifo.data_lock);
while (DECODER_FIFO_ISEMPTY(p_ac3dec->fifo))
{
if (p_ac3dec->b_die)
{
vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
return -1;
}
vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock);
}
p_ac3dec->p_ts = DECODER_FIFO_START (p_ac3dec->fifo)->p_first_ts;
p_ac3dec->p_data = DECODER_FIFO_START(*p_ac3dec->p_fifo)->p_first;
byte_stream = ac3_byte_stream (&p_ac3dec->ac3_decoder);
byte_stream->p_byte =
p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start;
byte_stream->p_end =
p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end;
byte_stream->p_byte = p_ac3dec->p_data->p_payload_start;
byte_stream->p_end = p_ac3dec->p_data->p_payload_end;
byte_stream->info = p_ac3dec;
vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
aout_fifo.i_channels = 2;
@ -204,7 +158,8 @@ static void RunThread (ac3dec_thread_t * p_ac3dec)
intf_DbgMsg ("ac3dec debug: running ac3 decoder thread (%p) (pid == %i)\n", p_ac3dec, getpid());
msleep (INPUT_PTS_DELAY);
/* FIXME ! Qu'est-ce que c'est que ce bordel !?!?!?!? --Meuuh */
//msleep (INPUT_PTS_DELAY);
/* Initializing the ac3 decoder thread */
if (InitThread (p_ac3dec)) /* XXX?? */
@ -264,10 +219,10 @@ static void RunThread (ac3dec_thread_t * p_ac3dec)
p_ac3dec->sync_ptr = 0;
}
if (DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts)
if (DECODER_FIFO_START(*p_ac3dec->p_fifo)->b_has_pts)
{
p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_ac3dec->fifo)->i_pts;
DECODER_FIFO_START(p_ac3dec->fifo)->b_has_pts = 0;
p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_ac3dec->p_fifo)->i_pts;
DECODER_FIFO_START(*p_ac3dec->p_fifo)->b_has_pts = 0;
}
else
{
@ -315,24 +270,26 @@ static void ErrorThread (ac3dec_thread_t * p_ac3dec)
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock (&p_ac3dec->fifo.data_lock);
vlc_mutex_lock (&p_ac3dec->p_fifo->data_lock);
/* Wait until a `die' order is sent */
while (!p_ac3dec->b_die)
{
/* Trash all received PES packets */
while (!DECODER_FIFO_ISEMPTY(p_ac3dec->fifo))
while (!DECODER_FIFO_ISEMPTY(*p_ac3dec->p_fifo))
{
input_NetlistFreePES (p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo));
DECODER_FIFO_INCSTART (p_ac3dec->fifo);
p_ac3dec->p_fifo->pf_delete_pes(p_ac3dec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_ac3dec->p_fifo));
DECODER_FIFO_INCSTART (*p_ac3dec->p_fifo);
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock);
vlc_cond_wait (&p_ac3dec->p_fifo->data_wait,
&p_ac3dec->p_fifo->data_lock);
}
/* We can release the lock before leaving */
vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
}
/*****************************************************************************
@ -369,19 +326,19 @@ void ac3_byte_stream_next (ac3_byte_stream_t * p_byte_stream)
{
/* We were reading the last TS packet of this PES packet... It's
* time to jump to the next PES packet */
if (p_ac3dec->p_ts->p_next_ts == NULL)
if (p_ac3dec->p_data->p_next == NULL)
{
int ptr;
/* We are going to read/write the start and end indexes of the
* decoder fifo and to use the fifo's conditional variable,
* that's why we need to take the lock before */
vlc_mutex_lock (&p_ac3dec->fifo.data_lock);
vlc_mutex_lock (&p_ac3dec->p_fifo->data_lock);
/* Is the input thread dying ? */
if (p_ac3dec->p_input->b_die)
if (p_ac3dec->p_fifo->b_die)
{
vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
return;
}
@ -390,43 +347,42 @@ void ac3_byte_stream_next (ac3_byte_stream_t * p_byte_stream)
* pointer to the current PES packet, and we weren't able to
* give it back to the netlist. That's why we free the PES
* packet first. */
input_NetlistFreePES (p_ac3dec->p_input, DECODER_FIFO_START(p_ac3dec->fifo));
p_ac3dec->p_fifo->pf_delete_pes(p_ac3dec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_ac3dec->p_fifo));
DECODER_FIFO_INCSTART (p_ac3dec->fifo);
DECODER_FIFO_INCSTART (*p_ac3dec->p_fifo);
while (DECODER_FIFO_ISEMPTY(p_ac3dec->fifo))
while (DECODER_FIFO_ISEMPTY(*p_ac3dec->p_fifo))
{
vlc_cond_wait (&p_ac3dec->fifo.data_wait, &p_ac3dec->fifo.data_lock);
vlc_cond_wait(&p_ac3dec->p_fifo->data_wait, &p_ac3dec->p_fifo->data_lock);
if (p_ac3dec->p_input->b_die)
if (p_ac3dec->p_fifo->b_die)
{
vlc_mutex_unlock (&(p_ac3dec->fifo.data_lock));
vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
return;
}
}
/* The next byte could be found in the next PES packet */
p_ac3dec->p_ts = DECODER_FIFO_START (p_ac3dec->fifo)->p_first_ts;
p_ac3dec->p_data = DECODER_FIFO_START(*p_ac3dec->p_fifo)->p_first;
/* parse ac3 magic header */
ptr = p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+2];
ptr = *(p_ac3dec->p_data->p_payload_start + 2);
ptr <<= 8;
ptr |= p_ac3dec->p_ts->buffer [p_ac3dec->p_ts->i_payload_start+3];
ptr |= *(p_ac3dec->p_data->p_payload_start + 3);
p_ac3dec->sync_ptr = ptr;
p_ac3dec->p_ts->i_payload_start += 4;
p_ac3dec->p_data->p_payload_start += 4;
/* We can release the fifo's data lock */
vlc_mutex_unlock (&p_ac3dec->fifo.data_lock);
vlc_mutex_unlock (&p_ac3dec->p_fifo->data_lock);
}
/* Perhaps the next TS packet of the current PES packet contains
* real data (ie its payload's size is greater than 0) */
else
{
p_ac3dec->p_ts = p_ac3dec->p_ts->p_next_ts;
p_ac3dec->p_data = p_ac3dec->p_data->p_next;
}
} while (p_ac3dec->p_ts->i_payload_start == p_ac3dec->p_ts->i_payload_end);
p_byte_stream->p_byte =
p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_start;
p_byte_stream->p_end =
p_ac3dec->p_ts->buffer + p_ac3dec->p_ts->i_payload_end;
} while (p_ac3dec->p_data->p_payload_start == p_ac3dec->p_data->p_payload_end);
p_byte_stream->p_byte = p_ac3dec->p_data->p_payload_start;
p_byte_stream->p_end = p_ac3dec->p_data->p_payload_end;
}

View File

@ -36,10 +36,10 @@ typedef struct ac3dec_thread_s
/*
* Input properties
*/
decoder_fifo_t fifo; /* stores the PES stream data */
input_thread_t * p_input;
ts_packet_t * p_ts;
int sync_ptr; /* sync ptr from ac3 magic header */
decoder_fifo_t * p_fifo; /* stores the PES stream data */
data_packet_t * p_data;
int sync_ptr; /* sync ptr from ac3 magic header */
adec_config_t * p_config;
/*
* Decoder properties
@ -58,5 +58,4 @@ typedef struct ac3dec_thread_s
/*****************************************************************************
* Prototypes
*****************************************************************************/
ac3dec_thread_t * ac3dec_CreateThread( input_thread_t * p_input );
void ac3dec_DestroyThread( ac3dec_thread_t * p_ac3dec );
vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config );

View File

@ -48,10 +48,9 @@
#include "debug.h" /* "input_netlist.h" */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "input.h" /* pes_packet_t */
#include "input_netlist.h" /* input_NetlistFreePES() */
#include "decoder_fifo.h" /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
#include "stream_control.h"
#include "input_ext-dec.h"
#include "audio_output.h" /* aout_fifo_t (for audio_decoder.h) */
@ -75,7 +74,7 @@ static void EndThread (adec_thread_t * p_adec);
* This function creates a new audio decoder thread, and returns a pointer to
* its description. On error, it returns NULL.
*****************************************************************************/
adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
vlc_thread_t adec_CreateThread ( adec_config_t * p_config )
{
adec_thread_t * p_adec;
@ -85,7 +84,7 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL )
{
intf_ErrMsg ( "adec error: not enough memory for adec_CreateThread() to create the new thread\n" );
return NULL;
return 0;
}
/*
@ -93,19 +92,9 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
*/
p_adec->b_die = 0;
p_adec->b_error = 0;
p_adec->p_config = p_config;
p_adec->p_fifo = p_config->decoder_config.p_decoder_fifo;
/*
* Initialize the input properties
*/
/* Initialize the decoder fifo's data lock and conditional variable and set
* its buffer as empty */
vlc_mutex_init ( &p_adec->fifo.data_lock );
vlc_cond_init ( &p_adec->fifo.data_wait );
p_adec->fifo.i_start = 0;
p_adec->fifo.i_end = 0;
/* Initialize the bit stream structure */
p_adec->p_input = p_input;
/*
* Initialize the decoder properties
@ -115,7 +104,7 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
/*
* Initialize the output properties
*/
p_adec->p_aout = p_input->p_aout;
p_adec->p_aout = p_config->p_aout;
p_adec->p_aout_fifo = NULL;
/* Spawn the audio decoder thread */
@ -123,37 +112,11 @@ adec_thread_t * adec_CreateThread ( input_thread_t * p_input )
{
intf_ErrMsg ("adec error: can't spawn audio decoder thread\n");
free (p_adec);
return NULL;
return 0;
}
intf_DbgMsg ("adec debug: audio decoder thread (%p) created\n", p_adec);
return p_adec;
}
/*****************************************************************************
* adec_DestroyThread: destroys an audio decoder thread
*****************************************************************************
* This function asks an audio decoder thread to terminate. This function has
* not to wait until the decoder thread has really died, because the killer (ie
* this function's caller) is the input thread, that's why we are sure that no
* other thread will try to access to this thread's descriptor after its
* destruction.
*****************************************************************************/
void adec_DestroyThread (adec_thread_t * p_adec)
{
intf_DbgMsg ("adec debug: requesting termination of audio decoder thread %p\n", p_adec);
/* Ask thread to kill itself */
p_adec->b_die = 1;
/* Make sure the decoder thread leaves the GetByte() function */
vlc_mutex_lock (&(p_adec->fifo.data_lock));
vlc_cond_signal (&(p_adec->fifo.data_wait));
vlc_mutex_unlock (&(p_adec->fifo.data_lock));
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join (p_adec->thread_id);
return p_adec->thread_id;
}
/*****************************************************************************
@ -171,24 +134,22 @@ static int InitThread (adec_thread_t * p_adec)
/* Our first job is to initialize the bit stream structure with the
* beginning of the input stream */
vlc_mutex_lock ( &p_adec->fifo.data_lock );
while ( DECODER_FIFO_ISEMPTY(p_adec->fifo) )
vlc_mutex_lock ( &p_adec->p_fifo->data_lock );
while ( DECODER_FIFO_ISEMPTY(*p_adec->p_fifo) )
{
if (p_adec->b_die)
{
vlc_mutex_unlock ( &p_adec->fifo.data_lock );
vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
return -1;
}
vlc_cond_wait ( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
vlc_cond_wait ( &p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock );
}
p_adec->p_ts = DECODER_FIFO_START ( p_adec->fifo )->p_first_ts;
p_adec->p_data = DECODER_FIFO_START ( *p_adec->p_fifo )->p_first;
byte_stream = adec_byte_stream ( &p_adec->audio_decoder );
byte_stream->p_byte =
p_adec->p_ts->buffer + p_adec->p_ts->i_payload_start;
byte_stream->p_end =
p_adec->p_ts->buffer + p_adec->p_ts->i_payload_end;
byte_stream->p_byte = p_adec->p_data->p_payload_start;
byte_stream->p_end = p_adec->p_data->p_payload_end;
byte_stream->info = p_adec;
vlc_mutex_unlock ( &p_adec->fifo.data_lock );
vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
aout_fifo.i_channels = 2;
@ -217,7 +178,8 @@ static void RunThread (adec_thread_t * p_adec)
intf_DbgMsg ( "adec debug: running audio decoder thread (%p) (pid == %i)\n", p_adec, getpid() );
msleep ( INPUT_PTS_DELAY );
/* You really suck */
//msleep ( INPUT_PTS_DELAY );
/* Initializing the audio decoder thread */
if( InitThread (p_adec) )
@ -256,11 +218,11 @@ static void RunThread (adec_thread_t * p_adec)
sync = 1;
}
if( DECODER_FIFO_START( p_adec->fifo)->b_has_pts )
if( DECODER_FIFO_START( *p_adec->p_fifo)->b_has_pts )
{
p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
DECODER_FIFO_START( p_adec->fifo )->i_pts;
DECODER_FIFO_START(p_adec->fifo)->b_has_pts = 0;
DECODER_FIFO_START( *p_adec->p_fifo )->i_pts;
DECODER_FIFO_START(*p_adec->p_fifo)->b_has_pts = 0;
}
else
{
@ -316,25 +278,25 @@ static void ErrorThread ( adec_thread_t *p_adec )
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock ( &p_adec->fifo.data_lock );
vlc_mutex_lock ( &p_adec->p_fifo->data_lock );
/* Wait until a `die' order is sent */
while ( !p_adec->b_die )
{
/* Trash all received PES packets */
while ( !DECODER_FIFO_ISEMPTY(p_adec->fifo) )
while ( !DECODER_FIFO_ISEMPTY(*p_adec->p_fifo) )
{
input_NetlistFreePES ( p_adec->p_input,
DECODER_FIFO_START(p_adec->fifo) );
DECODER_FIFO_INCSTART ( p_adec->fifo );
p_adec->p_fifo->pf_delete_pes ( p_adec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_adec->p_fifo) );
DECODER_FIFO_INCSTART ( *p_adec->p_fifo );
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait ( &p_adec->fifo.data_wait, &p_adec->fifo.data_lock );
vlc_cond_wait ( &p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock );
}
/* We can release the lock before leaving */
vlc_mutex_unlock ( &p_adec->fifo.data_lock );
vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
}
/*****************************************************************************
@ -373,17 +335,17 @@ void adec_byte_stream_next ( adec_byte_stream_t * p_byte_stream )
{
/* We were reading the last TS packet of this PES packet... It's
* time to jump to the next PES packet */
if (p_adec->p_ts->p_next_ts == NULL)
if (p_adec->p_data->p_next == NULL)
{
/* We are going to read/write the start and end indexes of the
* decoder fifo and to use the fifo's conditional variable,
* that's why we need to take the lock before */
vlc_mutex_lock (&p_adec->fifo.data_lock);
vlc_mutex_lock (&p_adec->p_fifo->data_lock);
/* Is the input thread dying ? */
if (p_adec->p_input->b_die)
if (p_adec->p_fifo->b_die)
{
vlc_mutex_unlock (&(p_adec->fifo.data_lock));
vlc_mutex_unlock (&(p_adec->p_fifo->data_lock));
return;
}
@ -392,40 +354,39 @@ void adec_byte_stream_next ( adec_byte_stream_t * p_byte_stream )
* pointer to the current PES packet, and we weren't able to
* give it back to the netlist. That's why we free the PES
* packet first. */
input_NetlistFreePES (p_adec->p_input, DECODER_FIFO_START(p_adec->fifo));
DECODER_FIFO_INCSTART (p_adec->fifo);
p_adec->p_fifo->pf_delete_pes (p_adec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_adec->p_fifo));
DECODER_FIFO_INCSTART (*p_adec->p_fifo);
while (DECODER_FIFO_ISEMPTY(p_adec->fifo))
while (DECODER_FIFO_ISEMPTY(*p_adec->p_fifo))
{
vlc_cond_wait (&p_adec->fifo.data_wait, &p_adec->fifo.data_lock);
if (p_adec->p_input->b_die)
vlc_cond_wait (&p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock);
if (p_adec->p_fifo->b_die)
{
vlc_mutex_unlock (&(p_adec->fifo.data_lock));
vlc_mutex_unlock (&(p_adec->p_fifo->data_lock));
return;
}
}
/* The next byte could be found in the next PES packet */
p_adec->p_ts = DECODER_FIFO_START (p_adec->fifo)->p_first_ts;
if (DECODER_FIFO_START (p_adec->fifo)->b_data_alignment)
p_adec->p_data = DECODER_FIFO_START (*p_adec->p_fifo)->p_first;
if (DECODER_FIFO_START (*p_adec->p_fifo)->b_data_alignment)
{
p_adec->align = 1;
}
/* We can release the fifo's data lock */
vlc_mutex_unlock (&p_adec->fifo.data_lock);
vlc_mutex_unlock (&p_adec->p_fifo->data_lock);
}
/* Perhaps the next TS packet of the current PES packet contains
* real data (ie its payload's size is greater than 0) */
else
{
p_adec->p_ts = p_adec->p_ts->p_next_ts;
p_adec->p_data = p_adec->p_data->p_next;
}
} while (p_adec->p_ts->i_payload_start == p_adec->p_ts->i_payload_end);
} while (p_adec->p_data->p_payload_start == p_adec->p_data->p_payload_end);
/* We've found a TS packet which contains interesting data... */
p_byte_stream->p_byte =
p_adec->p_ts->buffer + p_adec->p_ts->i_payload_start;
p_byte_stream->p_end =
p_adec->p_ts->buffer + p_adec->p_ts->i_payload_end;
p_byte_stream->p_byte = p_adec->p_data->p_payload_start;
p_byte_stream->p_end = p_adec->p_data->p_payload_end;
}

View File

@ -36,10 +36,11 @@ typedef struct adec_thread_s
/*
* Input properties
*/
decoder_fifo_t fifo; /* stores the PES stream data */
input_thread_t * p_input;
ts_packet_t * p_ts;
int align;
decoder_fifo_t * p_fifo; /* stores the PES stream data */
data_packet_t * p_data;
int align;
adec_config_t * p_config;
/*
* Decoder properties
@ -57,5 +58,4 @@ typedef struct adec_thread_s
/*****************************************************************************
* Prototypes
*****************************************************************************/
adec_thread_t * adec_CreateThread ( input_thread_t * p_input /* !! , aout_thread_t * p_aout !! */ );
void adec_DestroyThread ( adec_thread_t * p_adec );
vlc_thread_t adec_CreateThread ( adec_config_t * p_config );

File diff suppressed because it is too large Load Diff

47
src/input/input.h Normal file
View File

@ -0,0 +1,47 @@
/* Communication plugin -> input */
#define INPUT_READ_ONCE 7 /* We live in a world dominated by Ethernet. *
* Ethernet MTU is 1500 bytes, so in a UDP *
* packet we can put : 1500/188 = 7 TS *
* packets. Have a nice day and merry Xmas. */
/*****************************************************************************
* input_capabilities_t
*****************************************************************************
* This structure gives pointers to the useful methods of the plugin
*****************************************************************************/
typedef struct input_capabilities_s
{
/* Plugin properties */
int i_weight; /* for a given stream type, the plugin *
* with higher weight will be used */
/* Init/End */
int (* pf_probe)( struct input_thread_s * );
void (* pf_init)( struct input_thread_s * );
void (* pf_end)( struct input_thread_s * );
/* Read & Demultiplex */
void (* pf_read)( struct input_thread_s *,
struct data_packet_s * pp_packets[INPUT_READ_ONCE] );
void (* pf_demux)( struct input_thread_s *,
struct data_packet_s * );
/* Packet management facilities */
struct data_packet_s *(* pf_new_packet)( void *, size_t );
void (* pf_delete_packet)( void *,
struct data_packet_s * );
void (* pf_delete_pes)( void *, struct pes_packet_s * );
/* Stream control capabilities */
int (* pf_rewind)( struct input_thread_s * );
/* NULL if we don't support going *
* backwards (it's gonna be fun) */
int (* pf_seek)( struct input_thread_s *, off_t );
} input_capabilities_t;
/*****************************************************************************
* Prototypes from input_ext-dec.c
*****************************************************************************/
void InitBitstream ( struct bit_stream_s *, struct decoder_fifo_s * );
void NextDataPacket ( struct bit_stream_s * );

View File

@ -1,340 +0,0 @@
/*****************************************************************************
* input_ctrl.c: Decoder control
* Controls the extraction and the decoding of the programs elements carried
* within a stream.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Benoît Steiner <benny@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* "input.h" */
#include <stdio.h>
#include <netinet/in.h> /* ntohs */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "intf_msg.h"
#include "plugins.h"
#include "debug.h"
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "audio_output.h" /* aout_thread_t */
#include "audio_decoder.h" /* audiodec_t (for audio_decoder_thread.h) */
#include "audio_decoder_thread.h" /* adec_thread_t */
#include "ac3_decoder.h" /* ac3dec_t (for ac3_decoder_thread.h) */
#include "ac3_decoder_thread.h" /* ac3dec_thread_t */
#include "lpcm_decoder.h"
#include "lpcm_decoder_thread.h"
#include "video.h" /* picture_t (for video_output.h) */
#include "video_output.h" /* vout_thread_t */
#include "vdec_idct.h" /* dctelem_t (for video_parser.h) */
#include "vdec_motion.h" /* f_motion_t (for video_parser.h) */
#include "vpar_blocks.h" /* macroblock_t (for video_parser.h) */
#include "vpar_headers.h" /* sequence_t (for video_parser.h) */
#include "vpar_synchro.h" /* video_synchro_t (for video_parser.h) */
#include "video_parser.h" /* vpar_thread_t */
#include "spu_decoder.h" /* spudec_thread_t */
/*****************************************************************************
* input_AddPgrmElem: Start the extraction and the decoding of a program element
*****************************************************************************
* Add the element given by its PID in the list of PID to extract and spawn
* the decoding thread.
* This function only modifies the table of selected es, but must NOT modify
* the table of ES itself.
*****************************************************************************/
int input_AddPgrmElem( input_thread_t *p_input, int i_current_id )
{
int i_es_loop, i_selected_es_loop;
/* Since this function is intended to be called by interface, lock the
* elementary stream structure. */
vlc_mutex_lock( &p_input->es_lock );
/* Find out which PID we need. */
for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
{
if( p_input->p_es[i_es_loop].i_id == i_current_id )
{
if( p_input->p_es[i_es_loop].p_dec != NULL )
{
/* We already have a decoder for that PID. */
vlc_mutex_unlock( &p_input->es_lock );
intf_ErrMsg("input error: PID %d already selected\n",
i_current_id);
return( -1 );
}
intf_DbgMsg("Requesting selection of PID %d\n",
i_current_id);
/* Find a free spot in pp_selected_es. */
for( i_selected_es_loop = 0; p_input->pp_selected_es[i_selected_es_loop] != NULL
&& i_selected_es_loop < INPUT_MAX_SELECTED_ES; i_selected_es_loop++ );
if( i_selected_es_loop == INPUT_MAX_SELECTED_ES )
{
/* array full */
vlc_mutex_unlock( &p_input->es_lock );
intf_ErrMsg("input error: MAX_SELECTED_ES reached: try increasing it in config.h\n");
return( -1 );
}
/* Don't decode PSI streams ! */
if( p_input->p_es[i_es_loop].b_psi )
{
intf_ErrMsg("input_error: trying to decode PID %d which is the one of a PSI\n", i_current_id);
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
}
else
{
/* Spawn the decoder. */
switch( p_input->p_es[i_es_loop].i_type )
{
case AC3_AUDIO_ES:
/* Spawn ac3 thread */
if ( ((ac3dec_thread_t *)(p_input->p_es[i_es_loop].p_dec) =
ac3dec_CreateThread(p_input)) == NULL )
{
intf_ErrMsg( "Could not start ac3 decoder\n" );
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
}
break;
case LPCM_AUDIO_ES:
/* Spawn lpcm thread */
if ( ((lpcmdec_thread_t *)
(p_input->p_es[i_es_loop].p_dec) =
lpcmdec_CreateThread(p_input)) == NULL )
{
intf_ErrMsg( "LPCM Debug: Could not start "
"lpcm decoder\n" );
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
}
break;
case DVD_SPU_ES:
/* Spawn spu thread */
if ( ((spudec_thread_t *)
(p_input->p_es[i_es_loop].p_dec) =
spudec_CreateThread(p_input)) == NULL )
{
intf_ErrMsg( "Could not start spu decoder\n" );
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
}
break;
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
/* Spawn audio thread. */
if( ((adec_thread_t*)(p_input->p_es[i_es_loop].p_dec) =
adec_CreateThread( p_input )) == NULL )
{
intf_ErrMsg("Could not start audio decoder\n");
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
}
break;
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
/* Spawn video thread. */
if( ((vpar_thread_t*)(p_input->p_es[i_es_loop].p_dec) =
vpar_CreateThread( p_input )) == NULL )
{
intf_ErrMsg("Could not start video parser\n");
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
}
break;
default:
/* That should never happen. */
intf_DbgMsg( "input error: unknown stream (0x%.2x)\n",
p_input->p_es[i_es_loop].i_type);
vlc_mutex_unlock( &p_input->es_lock );
return( -1 );
break;
}
/* Initialise the demux */
p_input->p_es[i_es_loop].p_pes_packet = NULL;
p_input->p_es[i_es_loop].i_continuity_counter = 0xff;
p_input->p_es[i_es_loop].b_random = 0;
/* Mark stream to be demultiplexed. */
intf_DbgMsg( "Stream %d added in %d\n",
i_current_id, i_selected_es_loop);
p_input->pp_selected_es[i_selected_es_loop] =
&p_input->p_es[i_es_loop];
vlc_mutex_unlock( &p_input->es_lock );
return( 0 );
}
}
}
/* We haven't found this PID in the current stream. */
vlc_mutex_unlock( &p_input->es_lock );
intf_ErrMsg("input error: can't find PID %d\n", i_current_id);
return( -1 );
}
/*****************************************************************************
* input_DelPgrmElem: Stop the decoding of a program element
*****************************************************************************
* Stop the extraction of the element given by its PID and kill the associated
* decoder thread
* This function only modifies the table of selected es, but must NOT modify
* the table of ES itself.
*****************************************************************************/
int input_DelPgrmElem( input_thread_t *p_input, int i_current_id )
{
int i_selected_es_loop, i_last_selected;
/* Since this function is intended to be called by interface, lock the
structure. */
vlc_mutex_lock( &p_input->es_lock );
/* Find out which PID we need. */
for( i_selected_es_loop = 0; i_selected_es_loop < INPUT_MAX_SELECTED_ES;
i_selected_es_loop++ )
{
if( p_input->pp_selected_es[i_selected_es_loop] )
{
if( p_input->pp_selected_es[i_selected_es_loop]->i_id == i_current_id )
{
if( !(p_input->pp_selected_es[i_selected_es_loop]->p_dec) )
{
/* We don't have a decoder for that PID. */
vlc_mutex_unlock( &p_input->es_lock );
intf_ErrMsg("input error: PID %d already deselected\n",
i_current_id);
return( -1 );
}
intf_DbgMsg("input debug: requesting termination of PID %d\n",
i_current_id);
/* Cancel the decoder. */
switch( p_input->pp_selected_es[i_selected_es_loop]->i_type )
{
case AC3_AUDIO_ES:
ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
break;
case LPCM_AUDIO_ES:
lpcmdec_DestroyThread( (lpcmdec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
break;
case DVD_SPU_ES:
spudec_DestroyThread( (spudec_thread_t *)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
break;
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) );
break;
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_selected_es_loop]->p_dec) /*, NULL */ );
break;
}
/* Unmark stream. */
p_input->pp_selected_es[i_selected_es_loop]->p_dec = NULL;
/* Find last selected stream. */
for( i_last_selected = i_selected_es_loop;
p_input->pp_selected_es[i_last_selected]
&& i_last_selected < INPUT_MAX_SELECTED_ES;
i_last_selected++ );
/* Exchange streams. */
p_input->pp_selected_es[i_selected_es_loop] =
p_input->pp_selected_es[i_last_selected];
p_input->pp_selected_es[i_last_selected] = NULL;
vlc_mutex_unlock( &p_input->es_lock );
return( 0 );
}
}
}
/* We haven't found this PID in the current stream. */
vlc_mutex_unlock( &p_input->es_lock );
intf_ErrMsg("input error: can't find PID %d\n", i_current_id);
return( -1 );
}
/*****************************************************************************
* input_IsElemRecv: Test if an element given by its PID is currently received
*****************************************************************************
* Cannot return the position of the es in the pp_selected_es, for it can
* change once we have released the lock
*****************************************************************************/
boolean_t input_IsElemRecv( input_thread_t *p_input, int i_id )
{
boolean_t b_is_recv = 0;
int i_index = 0;
/* Since this function is intended to be called by interface, lock the
structure. */
vlc_mutex_lock( &p_input->es_lock );
/* Scan the table */
while( i_index < INPUT_MAX_SELECTED_ES && !p_input->pp_selected_es[i_index] )
{
if( p_input->pp_selected_es[i_index]->i_id == i_id )
{
b_is_recv = 1;
break;
}
}
/* Unlock the structure */
vlc_mutex_unlock( &p_input->es_lock );
return( b_is_recv );
}

View File

@ -1,40 +0,0 @@
/*****************************************************************************
* input_ctrl.h: Decodeur control
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Requires:
* "config.h"
* "common.h"
* "mtime.h"
*****************************************************************************/
/*****************************************************************************
* Prototypes
*****************************************************************************/
int input_AddPgrmElem( input_thread_t *p_input, int i_current_pid );
int input_DelPgrmElem( input_thread_t *p_input, int i_current_pid );
boolean_t input_IsElemRecv( input_thread_t *p_input, int i_pid );

157
src/input/input_ext-dec.c Normal file
View File

@ -0,0 +1,157 @@
/*****************************************************************************
* input_ext-dec.c: services to the decoders
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
*
* Authors:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "intf_msg.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "input.h"
/*****************************************************************************
* InitBitstream: initialize a bit_stream_t structure
*****************************************************************************/
void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo )
{
p_bit_stream->p_decoder_fifo = p_fifo;
p_bit_stream->pf_next_data_packet = NextDataPacket;
/* Get the first data packet. */
vlc_mutex_lock( &p_fifo->data_lock );
while ( DECODER_FIFO_ISEMPTY( *p_fifo ) )
{
if ( p_fifo->b_die )
{
vlc_mutex_unlock( &p_fifo->data_lock );
return;
}
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
}
p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first;
p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
p_bit_stream->p_end = p_bit_stream->p_data->p_payload_end;
p_bit_stream->fifo.buffer = 0;
p_bit_stream->fifo.i_available = 0;
vlc_mutex_unlock( &p_fifo->data_lock );
}
/*****************************************************************************
* NextDataPacket: go to the next data packet
*****************************************************************************/
void NextDataPacket( bit_stream_t * p_bit_stream )
{
WORD_TYPE buffer_left;
/* FIXME : not portable in a 64bit environment */
int i_bytes_left;
decoder_fifo_t * p_fifo = p_bit_stream->p_decoder_fifo;
/* Buffer used at the end of a decoder thread, to give it zero
* values if needed. */
static byte_t p_zero[64] = { 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0 };
/* Put the remaining bytes (not aligned on a word boundary) in a
* temporary buffer. */
i_bytes_left = p_bit_stream->p_end - p_bit_stream->p_byte;
buffer_left = *((WORD_TYPE *)p_bit_stream->p_end - 1);
/* We are looking for the next data packet that contains real data,
* and not just a PES header */
do
{
/* We were reading the last data packet of this PES packet... It's
* time to jump to the next PES packet */
if( p_bit_stream->p_data->p_next == NULL )
{
/* We are going to read/write the start and end indexes of the
* decoder fifo and to use the fifo's conditional variable,
* that's why we need to take the lock before. */
vlc_mutex_lock( &p_fifo->data_lock );
/* Is the input thread dying ? */
if( p_fifo->b_die )
{
vlc_mutex_unlock( &p_fifo->data_lock );
p_bit_stream->p_byte = p_zero;
p_bit_stream->p_end = &p_zero[sizeof(p_zero) - 1];
return;
}
/* We should increase the start index of the decoder fifo, but
* if we do this now, the input thread could overwrite the
* pointer to the current PES packet, and we weren't able to
* give it back to the netlist. That's why we free the PES
* packet first. */
p_fifo->pf_delete_pes( p_fifo->p_packets_mgt,
DECODER_FIFO_START( *p_fifo ) );
DECODER_FIFO_INCSTART( *p_fifo );
while( DECODER_FIFO_ISEMPTY( *p_fifo ) )
{
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
if( p_fifo->b_die )
{
vlc_mutex_unlock( &p_fifo->data_lock );
p_bit_stream->p_byte = p_zero;
p_bit_stream->p_end = &p_zero[sizeof(p_zero) - 1];
return;
}
}
/* The next byte could be found in the next PES packet */
p_bit_stream->p_data = DECODER_FIFO_START( *p_fifo )->p_first;
/* We can release the fifo's data lock */
vlc_mutex_unlock( &p_fifo->data_lock );
}
else
{
/* Perhaps the next data packet of the current PES packet contains
* real data (ie its payload's size is greater than 0). */
p_bit_stream->p_data = p_bit_stream->p_data->p_next;
}
} while ( p_bit_stream->p_data->p_payload_start
== p_bit_stream->p_data->p_payload_end );
/* We've found a data packet which contains interesting data... */
p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
p_bit_stream->p_end = p_bit_stream->p_data->p_payload_end;
/* Copy remaining bits of the previous packet */
*((WORD_TYPE *)p_bit_stream->p_byte - 1) = buffer_left;
p_bit_stream->p_byte -= i_bytes_left;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
/*****************************************************************************
* input_file.h: file streams functions interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Prototypes
*****************************************************************************/
int input_FileOpen ( input_thread_t *p_input );
int input_FileRead ( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count );
void input_FileClose ( input_thread_t *p_input );

View File

@ -1,159 +0,0 @@
/*****************************************************************************
* netlist.c: input thread
* Manages the TS and PES netlists (see netlist.h).
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* "input.h" */
#include <stdlib.h> /* free() */
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "intf_msg.h"
#include "debug.h"
#include "input.h"
#include "input_netlist.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/*****************************************************************************
* input_NetlistOpen: initialize the netlists buffers
*****************************************************************************/
int input_NetlistInit( input_thread_t *p_input )
{
int i_base, i_packets, i_iovec;
/* Initialize running indexes. */
#ifdef INPUT_LIFO_TS_NETLIST
p_input->netlist.i_ts_index = INPUT_TS_READ_ONCE;
#else
p_input->netlist.i_ts_start = 0;
p_input->netlist.i_ts_end = 0;
#endif
#ifdef INPUT_LIFO_PES_NETLIST
p_input->netlist.i_pes_index = 1; /* We allocate one PES at a time */
#else
p_input->netlist.i_pes_start = 0;
p_input->netlist.i_pes_end = 0;
#endif
/* Initialize all iovec from the TS netlist with the length of a packet */
for( i_iovec = 0; i_iovec < INPUT_MAX_TS + INPUT_TS_READ_ONCE; i_iovec++ )
{
p_input->netlist.p_ts_free[i_iovec].iov_len = TS_PACKET_SIZE;
}
/* Allocate a big piece of memory to contain the INPUT_MAX_TS TS packets */
if( ( p_input->netlist.p_ts_packets = malloc( (INPUT_MAX_TS + 1)
* sizeof(ts_packet_t) ) ) == NULL )
{
intf_ErrMsg("input error: can't allocate TS netlist buffer (%s)\n",
strerror(errno) );
return( -1 );
}
/* Allocate a big piece of memory to contain the INPUT_MAX_PES PES packets */
if( !( p_input->netlist.p_pes_packets = malloc( (INPUT_MAX_PES + 1)
* sizeof(pes_packet_t) ) ) )
{
intf_ErrMsg("input error: can't allocate PES netlist buffer (%s)\n",
strerror(errno) );
free( p_input->netlist.p_ts_packets );
return( -1 );
}
/* Insert TS packets into the TS netlist */
#ifdef INPUT_LIFO_TS_NETLIST
i_base = p_input->netlist.i_ts_index;
#else
i_base = p_input->netlist.i_ts_start;
#endif
/* i_base is now the base address to locate free packets in the netlist */
for( i_packets = 0; i_packets < INPUT_MAX_TS + 1; i_packets++ )
{
p_input->netlist.p_ts_free[i_base + i_packets].iov_base
= (void *)(p_input->netlist.p_ts_packets + i_packets);
/* Initialize TS length. */
(p_input->netlist.p_ts_packets[i_packets]).i_payload_end = TS_PACKET_SIZE;
}
/* Insert PES packets into the netlist */
#ifdef INPUT_LIFO_PES_NETLIST
i_base = p_input->netlist.i_pes_index;
#else
i_base = p_input->netlist.i_pes_start;
#endif
/* i_base is now the base address to locate free packets in the netlist */
for( i_packets = 0; i_packets < INPUT_MAX_PES + 1; i_packets++ )
{
p_input->netlist.p_pes_free[i_base + i_packets]
= p_input->netlist.p_pes_packets + i_packets;
}
/* the p_pes_header_save buffer is allocated on the fly by the PES
demux if needed, and freed with the PES packet when the netlist
is destroyed. We initialise the field to NULL so that the demux
can determine if it has already allocated this buffer or not. */
for( i_packets = 0; i_packets < INPUT_MAX_PES + 1; i_packets++ )
{
p_input->netlist.p_pes_packets[i_packets].p_pes_header_save = NULL;
}
return( 0 );
}
/*****************************************************************************
* input_NetlistClean: clean the netlists buffers
*****************************************************************************/
void input_NetlistEnd( input_thread_t *p_input )
{
int i;
/* free TS netlist */
free( p_input->netlist.p_ts_packets );
/* free the pes_buffer_save buffers of the PES packets if they have
been allocated */
for( i = 0; i < INPUT_MAX_PES + 1; i++ )
{
byte_t* p_buffer = p_input->netlist.p_pes_packets[i].p_pes_header_save;
if(p_buffer)
free(p_buffer);
}
/* free PES netlist */
free( p_input->netlist.p_pes_packets );
}

View File

@ -1,271 +0,0 @@
/*****************************************************************************
* network.c: functions to read from the network
* Manages a socket.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Benoît Steiner <benny@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* "input.h" */
#include <string.h> /* strerror() */
#include <unistd.h> /* close() */
#include <errno.h> /* errno */
#include <sys/time.h> /* "input_network.h" */
#if defined(SYS_BSD) || defined(SYS_BEOS)
#include <sys/socket.h> /* struct sockaddr */
#endif
#include <netdb.h> /* servent, getservbyname(), hostent, gethostbyname() */
#include <netinet/in.h> /* sockaddr_in, htons(), htonl() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "netutils.h"
#include "input.h"
#include "input_network.h"
#include "input_vlan.h"
#include "intf_msg.h"
#include "plugins.h"
#include "main.h"
/*****************************************************************************
* input_NetworkOpen: initialize a network stream
*****************************************************************************/
int input_NetworkOpen( input_thread_t *p_input )
{
int i_socket_option;
struct sockaddr_in sa_in;
char psz_hostname[INPUT_MAX_SOURCE_LENGTH];
/* First and foremost, in the VLAN method, join the desired VLAN. */
if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
{
if( input_VlanJoin( p_input->i_vlan ) )
{
intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
return( 1 );
}
}
/* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
* protocol */
if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
{
intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
return( 1 );
}
/*
* Set up the options of the socket
*/
/* Set SO_REUSEADDR option which allows to re-bind() a busy port */
i_socket_option = 1;
if( setsockopt( p_input->i_handle,
SOL_SOCKET,
SO_REUSEADDR,
&i_socket_option,
sizeof( i_socket_option ) ) == (-1) )
{
intf_ErrMsg("error: can't configure socket (SO_REUSEADDR: %s)\n", strerror(errno));
close( p_input->i_handle );
return( 1 );
}
#ifndef SYS_BEOS
/* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
* packet loss caused by scheduling problems */
i_socket_option = 524288;
if( setsockopt( p_input->i_handle,
SOL_SOCKET,
SO_RCVBUF,
&i_socket_option,
sizeof( i_socket_option ) ) == (-1) )
{
intf_ErrMsg("error: can't configure socket (SO_RCVBUF: %s)\n", strerror(errno));
close( p_input->i_handle );
return( 1 );
}
#endif /* SYS_BEOS */
/*
* Bind the socket
*/
/* Use default port if not specified */
if( p_input->i_port == 0 )
{
p_input->i_port = main_GetIntVariable( INPUT_PORT_VAR, INPUT_PORT_DEFAULT );
}
/* See if the user requested broadcast method */
if( main_GetIntVariable( INPUT_BROADCAST_VAR, INPUT_BROADCAST_DEFAULT ) )
{
p_input->i_method = INPUT_METHOD_TS_BCAST;
}
/* Find the address. */
switch( p_input->i_method )
{
case INPUT_METHOD_TS_BCAST:
case INPUT_METHOD_TS_VLAN_BCAST:
/* In that case, we have to bind with the broadcast address.
* broadcast addresses are very hard to find and depends on
* implementation, so we thought using a #define would be much
* simpler. */
#ifdef INPUT_BCAST_ADDR
if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
{
close( p_input->i_handle );
return( 1 );
}
#else
/* We bind with any address. Security problem ! */
if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
{
close( p_input->i_handle );
return( -1 );
}
#endif
break;
case INPUT_METHOD_TS_UCAST:
/* Unicast: bind with the local address. */
if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
{
intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
close( p_input->i_handle );
return( 1 );
}
if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
{
close( p_input->i_handle );
return( 1 );
}
break;
case INPUT_METHOD_TS_MCAST:
/* Multicast: bind with 239.0.0.1. */
if( BuildInetAddr( &sa_in, "239.0.0.1", p_input->i_port ) == (-1) )
{
close( p_input->i_handle );
return( 1 );
}
break;
}
/* Effectively bind the socket. */
if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
{
intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
close( p_input->i_handle );
return( 1 );
}
/*
* Connect the socket to the remote server
*/
/* Use default host if not specified */
if( p_input->p_source == NULL )
{
p_input->p_source = main_GetPszVariable( INPUT_SERVER_VAR, INPUT_SERVER_DEFAULT );
}
if( BuildInetAddr( &sa_in, p_input->p_source, htons(0) ) == (-1) )
{
close( p_input->i_handle );
return( -1 );
}
/* Connect the socket. */
if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
sizeof( sa_in ) ) == (-1) )
{
intf_ErrMsg("error: can't connect socket\n" );
close( p_input->i_handle );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* input_NetworkRead: read a stream from the network
*****************************************************************************
* Wait for data during up to 1 second and then abort if none is arrived. The
* number of bytes read is returned or -1 if an error occurs (so 0 is returned
* after a timeout)
* We don't have to make any test on presentation times, since we suppose
* the network server sends us data when we need it.
*****************************************************************************/
int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count )
{
fd_set rfds;
struct timeval tv;
int i_rc;
/* Watch the given fd to see when it has input */
FD_ZERO(&rfds);
FD_SET(p_input->i_handle, &rfds);
/* Wait up to 1 second */
tv.tv_sec = 1;
tv.tv_usec = 0;
i_rc = select(p_input->i_handle+1, &rfds, NULL, NULL, &tv);
if( i_rc > 0 )
{
/* Data were received before timeout */
i_rc = readv( p_input->i_handle, p_vector, i_count );
}
return( i_rc );
}
/*****************************************************************************
* input_NetworkClose: close a network stream
*****************************************************************************/
void input_NetworkClose( input_thread_t *p_input )
{
/* Close local socket. */
if( p_input->i_handle )
{
close( p_input->i_handle );
}
/* Leave vlan if required */
if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
{
input_VlanLeave( p_input->i_vlan );
}
}

View File

@ -1,29 +0,0 @@
/*****************************************************************************
* input_network.h: network functions interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Christophe Massiot <massot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Prototypes
*****************************************************************************/
int input_NetworkOpen ( input_thread_t *p_input );
int input_NetworkRead ( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count );
void input_NetworkClose ( input_thread_t *p_input );

View File

@ -1,155 +0,0 @@
/*****************************************************************************
* pcr.c: PCR management
* Manages structures containing PCR information.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* "input.h" */
#include <stdlib.h> /* atoi(), malloc(), free() */
#include <netinet/in.h> /* ntohl() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "debug.h"
#include "input.h"
#include "intf_msg.h"
#include "input_pcr.h"
/* Note:
*
* SYNCHRONIZATION METHOD
*
* We compute an average for the pcr because we want to eliminate the
* network jitter and keep the low frequency variations. The average is
* in fact a low pass filter and the jitter is a high frequency signal
* that is why it is eliminated by the filter/average.
*
* The low frequency variations enable us to synchronize the client clock
* with the server clock because they represent the time variation between
* the 2 clocks. Those variations (ie the filtered pcr) are used to compute
* the presentation dates for the audio and video frames. With those dates
* we can decoding (or trashing) the MPEG2 stream at "exactly" the same rate
* as it is sent by the server and so we keep the synchronization between
* the server and the client.
*
* It is a very important matter if you want to avoid underflow or overflow
* in all the FIFOs, but it may be not enough.
*
*/
/*****************************************************************************
* input_PcrReInit : Reinitialize the pcr_descriptor
*****************************************************************************/
void input_PcrReInit( input_thread_t *p_input )
{
ASSERT( p_input );
p_input->p_pcr->delta_pcr = 0;
p_input->p_pcr->last_pcr = 0;
p_input->p_pcr->c_average_count = 0;
}
/*****************************************************************************
* input_PcrInit : Initialize PCR decoder
*****************************************************************************/
int input_PcrInit( input_thread_t *p_input )
{
ASSERT( p_input );
if( (p_input->p_pcr = malloc(sizeof(pcr_descriptor_t))) == NULL )
{
return( -1 );
}
input_PcrReInit(p_input);
p_input->p_pcr->i_synchro_state = SYNCHRO_NOT_STARTED;
return( 0 );
}
/*****************************************************************************
* input_PcrDecode : Decode a PCR frame
*****************************************************************************/
void input_PcrDecode( input_thread_t *p_input, es_descriptor_t *p_es,
u8* p_pcr_data )
{
mtime_t pcr_time, sys_time, delta_pcr;
pcr_descriptor_t *p_pcr;
ASSERT( p_pcr_data );
ASSERT( p_input );
ASSERT( p_es );
p_pcr = p_input->p_pcr;
/* Convert the PCR in microseconde
* WARNING: do not remove the casts in the following calculation ! */
pcr_time = ( (( (mtime_t)U32_AT((u32*)p_pcr_data) << 1 ) | ( p_pcr_data[4] >> 7 )) * 300 ) / 27;
sys_time = mdate();
delta_pcr = sys_time - pcr_time;
if( p_es->b_discontinuity ||
( p_pcr->last_pcr != 0 &&
( (p_pcr->last_pcr - pcr_time) > PCR_MAX_GAP
|| (p_pcr->last_pcr - pcr_time) < - PCR_MAX_GAP ) ) )
{
intf_DbgMsg("input debug: input_PcrReInit()\n");
input_PcrReInit(p_input);
p_pcr->i_synchro_state = SYNCHRO_REINIT;
p_es->b_discontinuity = 0;
}
p_pcr->last_pcr = pcr_time;
if( p_pcr->c_average_count == PCR_MAX_AVERAGE_COUNTER )
{
p_pcr->delta_pcr =
( delta_pcr + (p_pcr->delta_pcr * (PCR_MAX_AVERAGE_COUNTER-1)) )
/ PCR_MAX_AVERAGE_COUNTER;
}
else
{
p_pcr->delta_pcr =
( delta_pcr + (p_pcr->delta_pcr * p_pcr->c_average_count) )
/ ( p_pcr->c_average_count + 1 );
p_pcr->c_average_count++;
}
if( p_pcr->i_synchro_state == SYNCHRO_NOT_STARTED )
{
p_pcr->i_synchro_state = SYNCHRO_START;
}
}
/*****************************************************************************
* input_PcrEnd : Clean PCR structures before dying
*****************************************************************************/
void input_PcrEnd( input_thread_t *p_input )
{
ASSERT( p_input );
free( p_input->p_pcr );
}

View File

@ -1,43 +0,0 @@
/*****************************************************************************
* input_pcr.h: PCR management interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/* Maximum number of samples used to compute the dynamic average value,
* it is also the maximum of c_average in the pcr_descriptor_struct.
* We use the following formula :
* new_average = (old_average * c_average + new_sample_value) / (c_average +1) */
#define PCR_MAX_AVERAGE_COUNTER 40
/* Maximum gap allowed between two PCRs. */
#define PCR_MAX_GAP 1000000
/* synchro states */
#define SYNCHRO_NOT_STARTED 1
#define SYNCHRO_START 2
#define SYNCHRO_REINIT 3
/*****************************************************************************
* Prototypes
*****************************************************************************/
int input_PcrInit ( input_thread_t *p_input );
void input_PcrDecode ( input_thread_t *p_input, es_descriptor_t* p_es,
u8* p_pcr_data );
void input_PcrEnd ( input_thread_t *p_input );

317
src/input/input_ps.c Normal file
View File

@ -0,0 +1,317 @@
/*****************************************************************************
* input_ps.c: PS demux and packet management
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
*
* Authors:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "intf_msg.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
#include "input.h"
#include "input_ps.h"
#include "mpeg_system.h"
#include "debug.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int PSProbe ( struct input_thread_s * );
static void PSRead ( struct input_thread_s *,
data_packet_t * p_packets[INPUT_READ_ONCE] );
static void PSInit ( struct input_thread_s * );
static void PSEnd ( struct input_thread_s * );
static struct data_packet_s * NewPacket ( void *, size_t );
static void DeletePacket( void *, struct data_packet_s * );
static void DeletePES ( void *, struct pes_packet_s * );
/*
* Data reading functions
*/
/*****************************************************************************
* PSProbe: verifies that the stream is a PS stream
*****************************************************************************/
static int PSProbe( input_thread_t * p_input )
{
/* verify that the first three bytes are 0x000001, or unscramble and
* re-do. */
return 1;
}
/*****************************************************************************
* PSInit: initializes PS structures
*****************************************************************************/
static void PSInit( input_thread_t * p_input )
{
thread_ps_data_t * p_method;
stream_ps_data_t * p_demux;
if( (p_method =
(thread_ps_data_t *)malloc( sizeof(thread_ps_data_t) )) == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_input->p_method_data = (void *)p_method;
/* Re-open the socket as a buffered FILE stream */
if( (p_method->stream = fdopen( p_input->i_handle, "r" )) == NULL )
{
intf_ErrMsg( "Cannot open file (%s)", strerror(errno) );
p_input->b_error = 1;
return;
}
fseek( p_method->stream, 0, SEEK_SET );
/* Pre-parse the stream to gather stream_descriptor_t. */
/* FIXME */
p_input->stream.pp_programs =
(pgrm_descriptor_t **)malloc( sizeof(pgrm_descriptor_t *) );
p_input->stream.pp_programs[0] =
(pgrm_descriptor_t *)malloc( sizeof(pgrm_descriptor_t) );
p_input->stream.pp_programs[0]->i_synchro_state = SYNCHRO_START;
p_input->stream.pp_programs[0]->delta_cr = 0;
p_input->stream.pp_programs[0]->last_cr = 0;
p_input->stream.pp_programs[0]->c_average_count = 0;
p_demux = (stream_ps_data_t *)malloc( sizeof( stream_ps_data_t) );
p_input->stream.p_demux_data = (void *)p_demux;
p_demux->b_is_PSM_complete = 0;
}
/*****************************************************************************
* PSEnd: frees unused data
*****************************************************************************/
static void PSEnd( input_thread_t * p_input )
{
free( p_input->stream.p_demux_data );
free( p_input->p_method_data );
}
/*****************************************************************************
* PSRead: reads a data packet
*****************************************************************************/
/* FIXME: read INPUT_READ_ONCE packet at once */
static void PSRead( input_thread_t * p_input,
data_packet_t * p_packets[INPUT_READ_ONCE] )
{
byte_t p_header[6];
data_packet_t * p_data;
int i_packet_size;
thread_ps_data_t * p_method;
p_method = (thread_ps_data_t *)p_input->p_method_data;
while( fread( p_header, 6, 1, p_method->stream ) != 1 )
{
int i_error;
if( (i_error = ferror( p_method->stream )) )
{
intf_ErrMsg( "Read 1 failed (%s)", strerror(i_error) );
p_input->b_error = 1;
return;
}
if( feof( p_method->stream ) )
{
intf_ErrMsg( "EOF reached" );
p_input->b_error = 1;
return;
}
}
if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
{
u32 i_buffer = U32_AT(p_header);
intf_ErrMsg( "Garbage at input (%x)\n", i_buffer );
while( (i_buffer & 0xFFFFFF00) != 0x100L )
{
i_buffer <<= 8;
i_buffer |= getc( p_method->stream );
if( feof(p_method->stream) || ferror(p_method->stream) )
{
p_input->b_error = 1;
return;
}
}
*(u32 *)p_header = i_buffer;
fread( p_header + 4, 2, 1, p_method->stream );
}
if( U32_AT(p_header) != 0x1BA )
{
i_packet_size = U16_AT(&p_header[4]);
}
else
{
i_packet_size = 8;
}
if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
{
p_input->b_error = 1;
intf_ErrMsg( "Out of memory" );
return;
}
memcpy( p_data->p_buffer, p_header, 6 );
/* FIXME: catch EINTR ! */
while( fread( p_data->p_buffer + 6, i_packet_size,
1, p_method->stream ) != 1 )
{
int i_error;
if( (i_error = ferror( p_method->stream)) )
{
intf_ErrMsg( "Read 1 failed (%s)", strerror(i_error) );
p_input->b_error = 1;
return;
}
if( feof( p_method->stream ) )
{
intf_ErrMsg( "EOF reached" );
p_input->b_error = 1;
return;
}
}
if( U32_AT(p_header) == 0x1BA )
{
/* stuffing_bytes */
byte_t p_garbage[8];
/* FIXME: catch EINTR ! */
if( (p_data->p_buffer[13] & 0x3) != 0 )
{
fread( p_garbage, p_garbage[0] & 0x3, 1,
p_method->stream );
}
}
memset( p_packets, 0, sizeof(p_packets) );
p_packets[0] = p_data;
}
/*
* Packet management utilities
*/
/*****************************************************************************
* NewPacket: allocates a data packet
*****************************************************************************/
static struct data_packet_s * NewPacket( void * p_garbage,
size_t i_size )
{
data_packet_t * p_data;
if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL )
{
intf_DbgMsg( "Out of memory" );
return NULL;
}
if( (p_data->p_buffer = (byte_t *)malloc( i_size )) == NULL )
{
intf_DbgMsg( "Out of memory" );
free( p_data );
return NULL;
}
p_data->p_payload_start = p_data->p_buffer;
p_data->p_payload_end = p_data->p_buffer + i_size;
return( p_data );
}
/*****************************************************************************
* DeletePacket: deletes a data packet
*****************************************************************************/
static void DeletePacket( void * p_garbage,
data_packet_t * p_data )
{
ASSERT(p_data);
ASSERT(p_data->p_buffer);
free( p_data->p_buffer );
free( p_data );
}
/*****************************************************************************
* DeletePES: deletes a PES packet and associated data packets
*****************************************************************************/
static void DeletePES( void * p_garbage, pes_packet_t * p_pes )
{
data_packet_t * p_data;
data_packet_t * p_next;
p_data = p_pes->p_first;
while( p_data != NULL )
{
p_next = p_data->p_next;
free( p_data->p_buffer );
free( p_data );
p_data = p_next;
}
free( p_pes );
}
/*****************************************************************************
* PSKludge: fakes a PS plugin (FIXME)
*****************************************************************************/
input_capabilities_t * PSKludge( void )
{
input_capabilities_t * p_plugin;
p_plugin = (input_capabilities_t *)malloc( sizeof(input_capabilities_t) );
p_plugin->pf_init = PSInit;
p_plugin->pf_read = PSRead;
p_plugin->pf_demux = input_DemuxPS; /* FIXME: use i_p_config_t ! */
p_plugin->pf_new_packet = NewPacket;
p_plugin->pf_delete_packet = DeletePacket;
p_plugin->pf_delete_pes = DeletePES;
p_plugin->pf_rewind = NULL;
p_plugin->pf_seek = NULL;
return( p_plugin );
}

12
src/input/input_ps.h Normal file
View File

@ -0,0 +1,12 @@
/*****************************************************************************
* Constants
*****************************************************************************/
/*****************************************************************************
* thread_ps_data_t: extension of input_thread_t
*****************************************************************************/
typedef struct thread_ps_data_s
{
/* We're necessarily reading a file. */
FILE * stream;
} thread_ps_data_t;

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
/*****************************************************************************
* psi.h: PSI management interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Benoît Steiner <benny@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Prototypes
*****************************************************************************/
int input_PsiInit ( input_thread_t *p_input );
void input_PsiDecode ( input_thread_t *p_input, psi_section_t* p_psi_section );
void input_PsiRead ( input_thread_t *p_input );
int input_PsiEnd ( input_thread_t *p_input );

View File

@ -1,9 +1,9 @@
/*****************************************************************************
* input_vlan.h: vlan input method
* input_ts.c: TS demux and netlist management
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* Copyright (C) 1998, 1999, 2000 VideoLAN
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Authors:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,18 +21,35 @@
*****************************************************************************/
/*****************************************************************************
* Required headers:
* <netinet/in.h>
* "threads.h"
* Preamble
*****************************************************************************/
#include "time_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
/*****************************************************************************
* Prototypes
* Local prototypes
*****************************************************************************/
int input_VlanCreate ( void );
void input_VlanDestroy ( void );
int input_VlanJoin ( int i_vlan_id );
void input_VlanLeave ( int i_vlan_id );
static int TSProbe ( struct input_thread_s * );
static void TSRead ( struct input_thread_s * );
static int TSInit ( struct input_thread_s * );
static void TSEnd ( struct input_thread_s * );
static struct data_packet_s * NewPacket ( struct input_thread_s *,
size_t );
static void DeletePacket( struct input_thread_s *,
struct data_packet_s * );
static void DeletePES ( struct input_thread_s *,
struct pes_packet_s * );
/*****************************************************************************
* TSProbe: verifies that the stream is a TS stream
*****************************************************************************/
static int TSProbe( input_thread_t * p_input )
{
/* verify that the first byte is 0x47 */
}
static void TSInit( input_thread_t * p_input )
{
/* Initialize netlist and TS structures */
}

17
src/input/input_ts.h Normal file
View File

@ -0,0 +1,17 @@
/*****************************************************************************
* thread_ts_data_t: extension of input_thread_t
*****************************************************************************/
typedef struct thread_ts_data_s
{
/* To use the efficiency of the scatter/gather IO operations without
* malloc'ing all the time, we implemented a FIFO of free data packets.
*/
vlc_mutex_lock lock;
struct iovec p_free_iovec[INPUT_MAX_TS + INPUT_TS_READ_ONCE];
data_packet_t * p_free_ts[INPUT_MAX_TS + INPUT_TS_READ_ONCE];
int i_free_start, i_free_end;
/* The free data packets are stored here : */
data_packet_t * p_data_packets;
byte_t * p_buffers;
} thread_ts_data_t;

View File

@ -1,310 +0,0 @@
/*****************************************************************************
* input_vlan.c: vlan management library
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <errno.h> /* ENOMEM */
#include <stdio.h> /* sprintf() */
#include <unistd.h> /* close() */
#include <string.h> /* strerror(), bzero() */
#include <stdlib.h> /* free() */
#include <sys/time.h> /* timeval */
#if defined(SYS_BSD) || defined(SYS_BEOS)
#include <netinet/in.h> /* struct in_addr */
#include <sys/socket.h> /* struct sockaddr */
#endif
#if defined(SYS_LINUX) || defined(SYS_BSD) || defined(SYS_GNU)
#include <arpa/inet.h> /* inet_ntoa(), inet_aton() */
#endif
#ifdef SYS_LINUX
#include <sys/ioctl.h> /* ioctl() */
#include <net/if.h> /* interface (arch-dependent) */
#endif
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "plugins.h"
#include "netutils.h"
#include "input_vlan.h"
#include "intf_msg.h"
#include "main.h"
/*****************************************************************************
* input_vlan_t: vlan library data
*****************************************************************************
* Store global vlan library data.
*****************************************************************************/
typedef struct input_vlan_s
{
int i_vlan_id; /* current vlan number */
mtime_t last_change; /* last change date */
} input_vlan_t;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/*****************************************************************************
* input_VlanCreate: initialize global vlan method data
*****************************************************************************
* Initialize vlan input method global data. This function should be called
* once before any input thread is created or any call to other input_Vlan*()
* function is attempted.
*****************************************************************************/
int input_VlanCreate( void )
{
#ifdef SYS_BEOS
intf_ErrMsg( "error: vlans are not supported under beos\n" );
return( 1 );
#else
/* Allocate structure */
p_main->p_vlan = malloc( sizeof( input_vlan_t ) );
if( p_main->p_vlan == NULL )
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM));
return( 1 );
}
/* Initialize structure */
p_main->p_vlan->i_vlan_id = 0;
p_main->p_vlan->last_change = 0;
intf_Msg("VLANs initialized\n");
return( 0 );
#endif /* SYS_BEOS */
}
/*****************************************************************************
* input_VlanDestroy: free global vlan method data
*****************************************************************************
* Free resources allocated by input_VlanMethodInit. This function should be
* called at the end of the program.
*****************************************************************************/
void input_VlanDestroy( void )
{
/* Return to default vlan */
if( p_main->p_vlan->i_vlan_id != 0 )
{
input_VlanJoin( 0 );
}
/* Free structure */
free( p_main->p_vlan );
}
/*****************************************************************************
* input_VlanLeave: leave a vlan
*****************************************************************************
* This function tells the vlan library that the designed interface is no more
* locked and than vlan changes can occur.
*****************************************************************************/
void input_VlanLeave( int i_vlan_id )
{
/* XXX?? */
}
/*****************************************************************************
* input_VlanJoin: join a vlan
*****************************************************************************
* This function will try to join a vlan. If the relevant interface is already
* on the good vlan, nothing will be done. Else, and if possible (if the
* interface is not locked), the vlan server will be contacted and a change will
* be requested. The function will block until the change is effective. Note
* that once a vlan is no more used, it's interface should be unlocked using
* input_VlanLeave().
* Non 0 will be returned in case of error.
*****************************************************************************/
int input_VlanJoin( int i_vlan_id )
{
#ifdef SYS_BEOS
return( -1 );
#else
#define SERVER "138.195.130.90"
#define INTERFACE "eth0"
/* default server port */
#define VLANSERVER_PORT 6010
int socket_cl;
int fromlen;
struct ifreq interface;
struct sockaddr_in sa_server;
struct sockaddr_in sa_client;
unsigned int version = 12;
char mess[80];
struct timeval *date_cl;
struct timeval time;
long unsigned int date;
int nbanswer;
char answer;
fd_set rfds;
/* If last change is too recent, wait a while */
if( mdate() - p_main->p_vlan->last_change < INPUT_VLAN_CHANGE_DELAY )
{
intf_Msg("Waiting before changing VLAN...\n");
mwait( p_main->p_vlan->last_change + INPUT_VLAN_CHANGE_DELAY );
}
p_main->p_vlan->last_change = mdate();
p_main->p_vlan->i_vlan_id = i_vlan_id;
intf_Msg("Joining VLAN %d (channel %d)\n", i_vlan_id + 2, i_vlan_id );
/*
*Looking for informations about the eth0 interface
*/
interface.ifr_addr.sa_family = AF_INET;
strcpy( interface.ifr_name, INTERFACE );
/*
* Initialysing the socket
*/
socket_cl = socket( AF_INET, SOCK_DGRAM, 0 );
intf_DbgMsg( "socket %d\n", socket_cl );
/*
* Getting the server's information
*/
bzero (&sa_server, sizeof (struct sockaddr_in));
sa_server.sin_family = AF_INET;
sa_server.sin_port = htons (VLANSERVER_PORT);
inet_aton (SERVER, &(sa_server.sin_addr));
/*
* Looking for the interface MAC address
*/
ioctl( socket_cl, SIOCGIFHWADDR, &interface );
intf_DbgMsg( "macaddr == %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
interface.ifr_hwaddr.sa_data[0] & 0xff,
interface.ifr_hwaddr.sa_data[1] & 0xff,
interface.ifr_hwaddr.sa_data[2] & 0xff,
interface.ifr_hwaddr.sa_data[3] & 0xff,
interface.ifr_hwaddr.sa_data[4] & 0xff,
interface.ifr_hwaddr.sa_data[5] & 0xff );
/*
* Getting date of the client
*/
date_cl = malloc (sizeof (struct timeval));
if (gettimeofday (date_cl, 0) == -1)
{
return -1;
}
date = date_cl->tv_sec;
intf_DbgMsg ("date %lu\n", date);
/*
* Build of the message
*/
sprintf (mess, "%d %u %lu %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n",
i_vlan_id, version, date,
interface.ifr_hwaddr.sa_data[0] & 0xff,
interface.ifr_hwaddr.sa_data[1] & 0xff,
interface.ifr_hwaddr.sa_data[2] & 0xff,
interface.ifr_hwaddr.sa_data[3] & 0xff,
interface.ifr_hwaddr.sa_data[4] & 0xff,
interface.ifr_hwaddr.sa_data[5] & 0xff);
intf_DbgMsg ("The message is %s\n", mess);
/*
* Open the socket 2
*/
bzero (&sa_client, sizeof (struct sockaddr_in));
sa_client.sin_family = AF_INET;
sa_client.sin_port = htons( 4312 );
sa_client.sin_addr.s_addr = INADDR_ANY;
intf_DbgMsg ("socket %d\n", socket_cl = socket( AF_INET, SOCK_DGRAM, 0 ));
fromlen = sizeof (struct sockaddr);
intf_DbgMsg( "bind %i\n", bind( socket_cl, (struct sockaddr *)(&sa_client), sizeof( struct sockaddr )));
/*
* Send the message
*/
sendto (socket_cl, mess, 80, 0, (struct sockaddr *)(&sa_server), sizeof (struct sockaddr ));
{
unsigned z;
printf("BBP\n");
z=0;
do {z++;} while (mess[z]!=':');
do {z++;} while (mess[z]!='e');
printf("meuuh %d %d\n",(unsigned)mess[z+3],(unsigned)mess[z+4]);
}
printf("BBP2\n");
/*
* Waiting 5 sec for one answer from the server
*/
time.tv_sec = 5;
time.tv_usec = 0;
FD_ZERO( &rfds );
FD_SET( socket_cl, &rfds );
nbanswer = select( socket_cl + 1, &rfds, NULL, NULL, &time);
if( nbanswer == 0 )
{
intf_DbgMsg( "no answer\n" );
}
else if( nbanswer == -1 )
{
intf_DbgMsg( "I couldn't recieve the answer\n" );
}
else
{
recvfrom (socket_cl, &answer, sizeof( char ), 0, (struct sockaddr *)(&sa_client), &fromlen);
intf_DbgMsg( "the answer : %hhd\n", answer );
if( answer == -1 )
{
intf_DbgMsg( "The server doesn't succed to create the thread\n" );
}
else if( answer == 0 )
{
intf_DbgMsg( "The server try to change the channel\n" );
}
else
{
intf_DbgMsg( "I don't know what is this answer !\n" );
}
}
/*
* Close the socket
*/
close( socket_cl);
return 0;
#endif
}

1019
src/input/mpeg_system.c Normal file

File diff suppressed because it is too large Load Diff

95
src/input/mpeg_system.h Normal file
View File

@ -0,0 +1,95 @@
/*****************************************************************************
* Constants
*****************************************************************************/
#define TS_PACKET_SIZE 188 /* Size of a TS packet */
#define PSI_SECTION_SIZE 4096 /* Maximum size of a PSI section */
#define PADDING_PACKET_SIZE 100 /* Size of the NULL packet inserted in case
* of data loss (this should be < 188). */
/*****************************************************************************
* psi_section_t
*****************************************************************************
* Describes a PSI section. Beware, it doesn't contain pointers to the TS
* packets that contain it as for a PES, but the data themselves
*****************************************************************************/
typedef struct psi_section_s
{
byte_t buffer[PSI_SECTION_SIZE];
/* Is there a section being decoded ? */
boolean_t b_running_section;
u16 i_length;
u16 i_current_position;
} psi_section_t;
/*****************************************************************************
* es_ts_data_t: extension of es_descriptor_t
*****************************************************************************/
typedef struct es_ts_data_s
{
boolean_t b_psi; /* Does the stream have to be handled by
* the PSI decoder ? */
psi_section_t * p_psi_section; /* PSI packets */
/* Markers */
int i_continuity_counter;
} es_ts_data_t;
/*****************************************************************************
* pgrm_ts_data_t: extension of pgrm_descriptor_t
*****************************************************************************/
typedef struct pgrm_ts_data_s
{
u16 i_pcr_pid; /* PCR ES, for TS streams */
} pgrm_ts_data_t;
/*****************************************************************************
* stream_ts_data_t: extension of stream_descriptor_t
*****************************************************************************/
typedef struct stream_ts_data_s
{
/* Program Association Table status */
u8 i_PAT_version; /* version number */
boolean_t b_is_PAT_complete; /* Is the PAT complete ? */
u8 i_known_PAT_sections;
/* Number of section we received so far */
byte_t a_known_PAT_sections[32];
/* Already received sections */
/* Program Map Table status */
boolean_t b_is_PMT_complete; /* Is the PMT complete ? */
u8 i_known_PMT_sections;
/* Number of section we received so far */
byte_t a_known_PMT_sections[32];
/* Already received sections */
/* Service Description Table status */
u8 i_SDT_version; /* version number */
boolean_t b_is_SDT_complete; /* Is the SDT complete ? */
u8 i_known_SDT_sections;
/* Number of section we received so far */
byte_t a_known_SDT_sections[32];
/* Already received sections */
} stream_ts_data_t;
/*****************************************************************************
* stream_ps_data_t: extension of stream_descriptor_t
*****************************************************************************/
typedef struct stream_ps_data_s
{
u8 i_PSM_version;
boolean_t b_is_PSM_complete;
} stream_ps_data_t;
/*****************************************************************************
* Prototypes
*****************************************************************************/
void input_DecodePES( struct input_thread_s *, struct es_descriptor_s * );
void input_ParsePES( struct input_thread_s *, struct es_descriptor_s * );
void input_GatherPES( struct input_thread_s *, struct data_packet_s *,
struct es_descriptor_s *, boolean_t, boolean_t );
void input_DemuxPS( struct input_thread_s *, struct data_packet_s * );
void input_DemuxTS( struct input_thread_s *, struct data_packet_s * );

View File

@ -40,7 +40,8 @@
#include "mtime.h"
#include "plugins.h"
#include "playlist.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "audio_output.h"
@ -176,18 +177,43 @@ intf_thread_t* intf_Create( void )
void intf_Run( intf_thread_t *p_intf )
{
char * psz_server = main_GetPszVariable( INPUT_SERVER_VAR, NULL );
input_config_t * p_input_config;
/* If a server was specified */
if( psz_server )
{
p_intf->p_input = input_CreateThread( INPUT_METHOD_TS_UCAST,
psz_server, 0, 0,
p_intf->p_vout, p_main->p_aout, NULL );
if( (p_input_config =
(input_config_t *)malloc( sizeof(input_config_t) )) == NULL )
{
intf_ErrMsg("Out of memory");
}
else
{
p_input_config->i_method = INPUT_METHOD_UCAST;
p_input_config->p_source = psz_server;
p_input_config->p_default_aout = p_main->p_aout;
p_input_config->p_default_vout = p_intf->p_vout;
p_intf->p_input = input_CreateThread( p_input_config, NULL );
}
}
/* Or if a file was specified */
else if( p_main->p_playlist->p_list )
else if( p_main->p_playlist->p_list != NULL )
{
p_intf->p_input = input_CreateThread( INPUT_METHOD_TS_FILE, NULL, 0, 0, p_main->p_intf->p_vout, p_main->p_aout, NULL );
if( (p_input_config =
(input_config_t *)malloc( sizeof(input_config_t) )) == NULL )
{
intf_ErrMsg("Out of memory");
}
else
{
p_input_config->i_method = INPUT_METHOD_FILE;
p_input_config->p_source = p_main->p_playlist->p_list[0]; /* FIXME ??? */
p_input_config->p_default_aout = p_main->p_aout;
p_input_config->p_default_vout = p_intf->p_vout;
p_intf->p_input = input_CreateThread( p_input_config, NULL );
}
}
/* Execute the initialization script - if a positive number is returned,
* the script could be executed but failed */
@ -262,6 +288,8 @@ void intf_Destroy( intf_thread_t *p_intf )
*****************************************************************************/
int intf_SelectChannel( intf_thread_t * p_intf, int i_channel )
{
/* FIXME */
#if 0
intf_channel_t * p_channel; /* channel */
/* Look for channel in array */
@ -294,6 +322,7 @@ int intf_SelectChannel( intf_thread_t * p_intf, int i_channel )
/* Channel does not exist */
intf_Msg("Channel %d does not exist\n", i_channel );
#endif
return( 1 );
}

View File

@ -59,7 +59,8 @@
#include "plugins.h"
#include "intf_msg.h"
#include "input.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "audio_output.h"
#include "intf_cmd.h"
#include "interface.h"
@ -463,6 +464,8 @@ static int SpawnInput( int i_argc, intf_arg_t *p_argv )
int i_port = 0; /* port parameter */
int i_vlan = 0; /* vlan parameter */
/* FIXME */
#if 0
/* Parse parameters - see command list above */
for ( i_arg = 1; i_arg < i_argc; i_arg++ )
{
@ -495,6 +498,7 @@ static int SpawnInput( int i_argc, intf_arg_t *p_argv )
p_main->p_intf->p_vout, p_main->p_aout,
NULL );
return( INTF_NO_ERROR );
#endif
}
/*****************************************************************************

View File

@ -42,8 +42,8 @@
#include "tests.h" /* TestMMX() */
#include "plugins.h"
#include "playlist.h"
#include "input_vlan.h"
#include "input_ps.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "intf_msg.h"
#include "interface.h"
@ -241,6 +241,8 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
/*
* Initialize shared resources and libraries
*/
/* FIXME: no VLANs */
#if 0
if( p_main->b_vlans && input_VlanCreate() )
{
/* On error during vlans initialization, switch off vlans */
@ -248,6 +250,7 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
"vlans management is deactivated\n" );
p_main->b_vlans = 0;
}
#endif
/*
* Open audio device and start aout thread
@ -290,10 +293,13 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
/*
* Free shared resources and libraries
*/
/* FIXME */
#if 0
if( p_main->b_vlans )
{
input_VlanDestroy();
}
#endif
/*
* Free plugin bank
@ -519,6 +525,8 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
main_PutPszVariable( YUV_METHOD_VAR, optarg );
break;
/* FIXME */
#if 0
/* DVD options */
case 'a':
if ( ! strcmp(optarg, "mpeg") )
@ -530,6 +538,7 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
else
main_PutIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_AC3 );
break;
#endif
case 'c':
main_PutIntVariable( INPUT_DVD_CHANNEL_VAR, atoi(optarg) );
break;

View File

@ -41,9 +41,8 @@
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "input.h" /* pes_packet_t */
#include "input_netlist.h" /* input_NetlistFreePES() */
#include "decoder_fifo.h" /* DECODER_FIFO_(ISEMPTY|START|INCSTART)() */
#include "stream_control.h"
#include "input_ext-dec.h"
#include "audio_output.h"
@ -63,7 +62,7 @@ static void EndThread (lpcmdec_thread_t * p_adec);
/*****************************************************************************
* lpcmdec_CreateThread: creates an lpcm decoder thread
*****************************************************************************/
lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
vlc_thread_t lpcmdec_CreateThread (adec_config_t * p_config)
{
lpcmdec_thread_t * p_lpcmdec;
intf_DbgMsg ( "LPCM Debug: creating lpcm decoder thread\n" );
@ -71,7 +70,7 @@ lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
/* Allocate the memory needed to store the thread's structure */
if ((p_lpcmdec = (lpcmdec_thread_t *)malloc (sizeof(lpcmdec_thread_t))) == NULL) {
intf_ErrMsg ( "LPCM Error: not enough memory for lpcmdec_CreateThread() to create the new thread\n" );
return NULL;
return 0;
}
/*
@ -79,58 +78,28 @@ lpcmdec_thread_t * lpcmdec_CreateThread (input_thread_t * p_input)
*/
p_lpcmdec->b_die = 0;
p_lpcmdec->b_error = 0;
p_lpcmdec->p_config = p_config;
p_lpcmdec->p_fifo = p_config->decoder_config.p_decoder_fifo;
/*
* Initialize the input properties
*/
/* Initialize the decoder fifo's data lock and conditional variable and set
* its buffer as empty */
vlc_mutex_init (&p_lpcmdec->fifo.data_lock);
vlc_cond_init (&p_lpcmdec->fifo.data_wait);
p_lpcmdec->fifo.i_start = 0;
p_lpcmdec->fifo.i_end = 0;
/* Initialize the lpcm decoder structures */
lpcm_init (&p_lpcmdec->lpcm_decoder);
/* Initialize the bit stream structure */
p_lpcmdec->p_input = p_input;
/*
* Initialize the output properties
*/
p_lpcmdec->p_aout = p_input->p_aout;
p_lpcmdec->p_aout = p_config->p_aout;
p_lpcmdec->p_aout_fifo = NULL;
/* Spawn the lpcm decoder thread */
if (vlc_thread_create(&p_lpcmdec->thread_id, "lpcm decoder", (vlc_thread_func_t)RunThread, (void *)p_lpcmdec)) {
intf_ErrMsg ( "LPCM Error: can't spawn lpcm decoder thread\n" );
free (p_lpcmdec);
return NULL;
return 0;
}
intf_DbgMsg ( "LPCM Debug: lpcm decoder thread (%p) created\n", p_lpcmdec );
return p_lpcmdec;
}
/*****************************************************************************
* lpcmdec_DestroyThread: destroys an lpcm decoder thread
*****************************************************************************/
void lpcmdec_DestroyThread (lpcmdec_thread_t * p_lpcmdec)
{
intf_DbgMsg ( "LPCM Debug: requesting termination of lpcm decoder thread %p\n", p_lpcmdec );
/* Ask thread to kill itself */
p_lpcmdec->b_die = 1;
/* Make sure the decoder thread leaves the GetByte() function */
vlc_mutex_lock (&(p_lpcmdec->fifo.data_lock));
vlc_cond_signal (&(p_lpcmdec->fifo.data_wait));
vlc_mutex_unlock (&(p_lpcmdec->fifo.data_lock));
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join (p_lpcmdec->thread_id);
return p_lpcmdec->thread_id;
}
/* Following functions are local */
@ -147,22 +116,20 @@ static int InitThread (lpcmdec_thread_t * p_lpcmdec)
/* Our first job is to initialize the bit stream structure with the
* beginning of the input stream */
vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
while (DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
while (DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
if (p_lpcmdec->b_die) {
vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
return -1;
}
vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
}
p_lpcmdec->p_ts = DECODER_FIFO_START (p_lpcmdec->fifo)->p_first_ts;
p_lpcmdec->p_data = DECODER_FIFO_START (*p_lpcmdec->p_fifo)->p_first;
byte_stream = lpcm_byte_stream (&p_lpcmdec->lpcm_decoder);
byte_stream->p_byte =
p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_start;
byte_stream->p_end =
p_lpcmdec->p_ts->buffer + p_lpcmdec->p_ts->i_payload_end;
byte_stream->p_byte = p_lpcmdec->p_data->p_payload_start;
byte_stream->p_end = p_lpcmdec->p_data->p_payload_end;
byte_stream->info = p_lpcmdec;
vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
aout_fifo.i_type = AOUT_ADEC_STEREO_FIFO;
aout_fifo.i_channels = 2;
@ -188,7 +155,8 @@ static void RunThread (lpcmdec_thread_t * p_lpcmdec)
intf_DbgMsg( "LPCM Debug: running lpcm decoder thread (%p) (pid== %i)\n", p_lpcmdec, getpid() );
msleep (INPUT_PTS_DELAY);
/* Fucking holy piece of shit ! */
//msleep (INPUT_PTS_DELAY);
/* Initializing the lpcm decoder thread */
if (InitThread (p_lpcmdec))
@ -212,10 +180,10 @@ static void RunThread (lpcmdec_thread_t * p_lpcmdec)
/* have to find a synchro point */
}
if (DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts)
if (DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts)
{
p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(p_lpcmdec->fifo)->i_pts;
DECODER_FIFO_START(p_lpcmdec->fifo)->b_has_pts = 0;
p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] = DECODER_FIFO_START(*p_lpcmdec->p_fifo)->i_pts;
DECODER_FIFO_START(*p_lpcmdec->p_fifo)->b_has_pts = 0;
}
else
{
@ -258,22 +226,23 @@ static void ErrorThread (lpcmdec_thread_t * p_lpcmdec)
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock (&p_lpcmdec->fifo.data_lock);
vlc_mutex_lock (&p_lpcmdec->p_fifo->data_lock);
/* Wait until a `die' order is sent */
while (!p_lpcmdec->b_die) {
/* Trash all received PES packets */
while (!DECODER_FIFO_ISEMPTY(p_lpcmdec->fifo)) {
input_NetlistFreePES (p_lpcmdec->p_input, DECODER_FIFO_START(p_lpcmdec->fifo));
DECODER_FIFO_INCSTART (p_lpcmdec->fifo);
while (!DECODER_FIFO_ISEMPTY(*p_lpcmdec->p_fifo)) {
p_lpcmdec->p_fifo->pf_delete_pes(p_lpcmdec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_lpcmdec->p_fifo));
DECODER_FIFO_INCSTART (*p_lpcmdec->p_fifo);
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait (&p_lpcmdec->fifo.data_wait, &p_lpcmdec->fifo.data_lock);
vlc_cond_wait (&p_lpcmdec->p_fifo->data_wait, &p_lpcmdec->p_fifo->data_lock);
}
/* We can release the lock before leaving */
vlc_mutex_unlock (&p_lpcmdec->fifo.data_lock);
vlc_mutex_unlock (&p_lpcmdec->p_fifo->data_lock);
}
/*****************************************************************************

View File

@ -36,10 +36,10 @@ typedef struct lpcmdec_thread_s
/*
* Input properties
*/
decoder_fifo_t fifo; /* stores the PES stream data */
input_thread_t * p_input;
ts_packet_t * p_ts;
int sync_ptr; /* sync ptr from lpcm magic header */
decoder_fifo_t * p_fifo; /* stores the PES stream data */
data_packet_t * p_data;
int sync_ptr; /* sync ptr from lpcm magic header */
adec_config_t * p_config;
/*
* Decoder properties
@ -58,5 +58,4 @@ typedef struct lpcmdec_thread_s
/*****************************************************************************
* Prototypes
*****************************************************************************/
lpcmdec_thread_t * lpcmdec_CreateThread( input_thread_t * p_input );
void lpcmdec_DestroyThread( lpcmdec_thread_t * p_lcpmdec );
vlc_thread_t lpcmdec_CreateThread( adec_config_t * p_config );

View File

@ -1,166 +0,0 @@
/*****************************************************************************
* decoder_fifo.c: auxiliaries functions used in decoder_fifo.h
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include "defs.h"
#include <sys/types.h> /* on BSD, uio.h needs types.h */
#include <sys/uio.h> /* for input.h */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "debug.h" /* XXX?? temporaire, requis par netlist.h */
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
void decoder_fifo_next( bit_stream_t * p_bit_stream )
{
/* We are looking for the next TS packet that contains real data,
* and not just a PES header */
do
{
/* We were reading the last TS packet of this PES packet... It's
* time to jump to the next PES packet */
if ( p_bit_stream->p_ts->p_next_ts == NULL )
{
/* We are going to read/write the start and end indexes of the
* decoder fifo and to use the fifo's conditional variable,
* that's why we need to take the lock before */
vlc_mutex_lock( &p_bit_stream->p_decoder_fifo->data_lock );
/* Is the input thread dying ? */
if ( p_bit_stream->p_input->b_die )
{
vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
return;
}
/* We should increase the start index of the decoder fifo, but
* if we do this now, the input thread could overwrite the
* pointer to the current PES packet, and we weren't able to
* give it back to the netlist. That's why we free the PES
* packet first. */
input_NetlistFreePES( p_bit_stream->p_input, DECODER_FIFO_START(*p_bit_stream->p_decoder_fifo) );
DECODER_FIFO_INCSTART( *p_bit_stream->p_decoder_fifo );
while ( DECODER_FIFO_ISEMPTY(*p_bit_stream->p_decoder_fifo) )
{
vlc_cond_wait( &p_bit_stream->p_decoder_fifo->data_wait, &p_bit_stream->p_decoder_fifo->data_lock );
if ( p_bit_stream->p_input->b_die )
{
vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
return;
}
}
/* The next byte could be found in the next PES packet */
p_bit_stream->p_ts = DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->p_first_ts;
/* We can release the fifo's data lock */
vlc_mutex_unlock( &p_bit_stream->p_decoder_fifo->data_lock );
}
/* Perhaps the next TS packet of the current PES packet contains
* real data (ie its payload's size is greater than 0) */
else
{
p_bit_stream->p_ts = p_bit_stream->p_ts->p_next_ts;
}
} while ( p_bit_stream->p_ts->i_payload_start == p_bit_stream->p_ts->i_payload_end );
/* We've found a TS packet which contains interesting data... */
p_bit_stream->p_byte = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_start;
p_bit_stream->p_end = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_end;
}
void PeekNextPacket( bit_stream_t * p_bit_stream )
{
WORD_TYPE buffer_left;
int i_bytes_left; /* FIXME : not portable in a 64bit environment */
/* Put the remaining bytes (not aligned on a word boundary) in a
* temporary buffer. */
i_bytes_left = p_bit_stream->p_end - p_bit_stream->p_byte;
buffer_left = *((WORD_TYPE *)p_bit_stream->p_end - 1);
/* We are looking for the next TS packet that contains real data,
* and not just a PES header */
do
{
/* We were reading the last TS packet of this PES packet... It's
* time to jump to the next PES packet */
if ( p_bit_stream->p_ts->p_next_ts == NULL )
{
/* We are going to read/write the start and end indexes of the
* decoder fifo and to use the fifo's conditional variable,
* that's why we need to take the lock before */
vlc_mutex_lock( &p_bit_stream->p_decoder_fifo->data_lock );
/* Is the input thread dying ? */
if ( p_bit_stream->p_input->b_die )
{
vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
return;
}
/* We should increase the start index of the decoder fifo, but
* if we do this now, the input thread could overwrite the
* pointer to the current PES packet, and we weren't able to
* give it back to the netlist. That's why we free the PES
* packet first. */
input_NetlistFreePES( p_bit_stream->p_input, DECODER_FIFO_START(*p_bit_stream->p_decoder_fifo) );
DECODER_FIFO_INCSTART( *p_bit_stream->p_decoder_fifo );
while ( DECODER_FIFO_ISEMPTY(*p_bit_stream->p_decoder_fifo) )
{
vlc_cond_wait( &p_bit_stream->p_decoder_fifo->data_wait, &p_bit_stream->p_decoder_fifo->data_lock );
if ( p_bit_stream->p_input->b_die )
{
vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
return;
}
}
/* The next byte could be found in the next PES packet */
p_bit_stream->p_ts = DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->p_first_ts;
/* We can release the fifo's data lock */
vlc_mutex_unlock( &p_bit_stream->p_decoder_fifo->data_lock );
}
/* Perhaps the next TS packet of the current PES packet contains
* real data (ie its payload's size is greater than 0) */
else
{
p_bit_stream->p_ts = p_bit_stream->p_ts->p_next_ts;
}
} while ( p_bit_stream->p_ts->i_payload_start == p_bit_stream->p_ts->i_payload_end );
/* We've found a TS packet which contains interesting data... */
p_bit_stream->p_byte = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_start;
p_bit_stream->p_end = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_end;
/* Copy remaining bits of the previous packet */
*((WORD_TYPE *)p_bit_stream->p_byte - 1) = buffer_left;
p_bit_stream->p_byte -= i_bytes_left;
}

View File

@ -42,9 +42,8 @@
#include "intf_msg.h"
#include "debug.h" /* ASSERT */
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"
@ -67,7 +66,7 @@ static void EndThread ( spudec_thread_t *p_spudec );
/*****************************************************************************
* spudec_CreateThread: create a spu decoder thread
*****************************************************************************/
spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
vlc_thread_t spudec_CreateThread( vdec_config_t * p_config )
{
spudec_thread_t * p_spudec;
@ -77,7 +76,7 @@ spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
if ( (p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) )) == NULL )
{
intf_ErrMsg("spudec error: not enough memory for spudec_CreateThread() to create the new thread\n");
return( NULL );
return( 0 );
}
/*
@ -85,24 +84,11 @@ spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
*/
p_spudec->b_die = 0;
p_spudec->b_error = 0;
/*
* Initialize the input properties
*/
/* Initialize the decoder fifo's data lock and conditional variable and set
* its buffer as empty */
vlc_mutex_init( &p_spudec->fifo.data_lock );
vlc_cond_init( &p_spudec->fifo.data_wait );
p_spudec->fifo.i_start = 0;
p_spudec->fifo.i_end = 0;
/* Initialize the bit stream structure */
p_spudec->bit_stream.p_input = p_input;
p_spudec->bit_stream.p_decoder_fifo = &p_spudec->fifo;
p_spudec->bit_stream.fifo.buffer = 0;
p_spudec->bit_stream.fifo.i_available = 0;
p_spudec->p_config = p_config;
p_spudec->p_fifo = p_config->decoder_config.p_decoder_fifo;
/* Get the video output informations */
p_spudec->p_vout = p_input->p_vout;
p_spudec->p_vout = p_config->p_vout;
/* Spawn the spu decoder thread */
if ( vlc_thread_create(&p_spudec->thread_id, "spu decoder",
@ -110,36 +96,11 @@ spudec_thread_t * spudec_CreateThread( input_thread_t * p_input )
{
intf_ErrMsg("spudec error: can't spawn spu decoder thread\n");
free( p_spudec );
return( NULL );
return( 0 );
}
intf_DbgMsg("spudec debug: spu decoder thread (%p) created\n", p_spudec);
return( p_spudec );
}
/*****************************************************************************
* spudec_DestroyThread: destroy a spu decoder thread
*****************************************************************************
* Destroy and terminate thread. This function will return 0 if the thread could
* be destroyed, and non 0 else. The last case probably means that the thread
* was still active, and another try may succeed.
*****************************************************************************/
void spudec_DestroyThread( spudec_thread_t *p_spudec )
{
intf_DbgMsg( "spudec debug: requesting termination of "
"spu decoder thread %p\n", p_spudec);
/* Ask thread to kill itself */
p_spudec->b_die = 1;
/* Warn the decoder that we're quitting */
vlc_mutex_lock( &p_spudec->fifo.data_lock );
vlc_cond_signal( &p_spudec->fifo.data_wait );
vlc_mutex_unlock( &p_spudec->fifo.data_lock );
/* Waiting for the decoder thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join( p_spudec->thread_id );
return( p_spudec->thread_id );
}
/* following functions are local */
@ -155,23 +116,8 @@ static int InitThread( spudec_thread_t *p_spudec )
{
intf_DbgMsg("spudec debug: initializing spu decoder thread %p\n", p_spudec);
/* Our first job is to initialize the bit stream structure with the
* beginning of the input stream */
vlc_mutex_lock( &p_spudec->fifo.data_lock );
while ( DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
{
if ( p_spudec->b_die )
{
vlc_mutex_unlock( &p_spudec->fifo.data_lock );
return( 1 );
}
vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
}
p_spudec->bit_stream.p_ts = DECODER_FIFO_START( p_spudec->fifo )->p_first_ts;
p_spudec->bit_stream.p_byte = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_start;
p_spudec->bit_stream.p_end = p_spudec->bit_stream.p_ts->buffer + p_spudec->bit_stream.p_ts->i_payload_end;
vlc_mutex_unlock( &p_spudec->fifo.data_lock );
p_spudec->p_config->decoder_config.pf_init_bit_stream( &p_spudec->bit_stream,
p_spudec->p_config->decoder_config.p_decoder_fifo );
/* Mark thread as running and return */
intf_DbgMsg( "spudec debug: InitThread(%p) succeeded\n", p_spudec );
@ -211,7 +157,7 @@ static void RunThread( spudec_thread_t *p_spudec )
unsigned char * p_spu_data;
subpicture_t * p_spu = NULL;
while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
while( !DECODER_FIFO_ISEMPTY(*p_spudec->p_fifo) )
{
/* wait for the next SPU ID.
* XXX: We trash 0xff bytes since they probably come from
@ -232,7 +178,7 @@ static void RunThread( spudec_thread_t *p_spudec )
i_index = 2;
/* get the useful PES size (real size - 10) */
i_pes_size = DECODER_FIFO_START(p_spudec->fifo)->i_pes_size - 9;
i_pes_size = DECODER_FIFO_START(*p_spudec->p_fifo)->i_pes_size - 9;
i_pes_count = 1;
/* the RLE stuff size */
@ -249,7 +195,7 @@ static void RunThread( spudec_thread_t *p_spudec )
/* get display time */
p_spu->begin_date = p_spu->end_date
= DECODER_FIFO_START(p_spudec->fifo)->i_pts;
= DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts;
/* getting the RLE part */
while( i_index++ < i_rle_size )
@ -357,11 +303,11 @@ static void RunThread( spudec_thread_t *p_spudec )
{
/* Unexpected PES packet - trash it */
intf_ErrMsg( "spudec: trying to recover from bad packet\n" );
vlc_mutex_lock( &p_spudec->fifo.data_lock );
input_NetlistFreePES( p_spudec->bit_stream.p_input,
DECODER_FIFO_START(p_spudec->fifo) );
DECODER_FIFO_INCSTART( p_spudec->fifo );
vlc_mutex_unlock( &p_spudec->fifo.data_lock );
vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_spudec->p_fifo) );
DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
}
}
@ -392,24 +338,25 @@ static void ErrorThread( spudec_thread_t *p_spudec )
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock( &p_spudec->fifo.data_lock );
vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
/* Wait until a `die' order is sent */
while( !p_spudec->b_die )
{
/* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
while( !DECODER_FIFO_ISEMPTY(*p_spudec->p_fifo) )
{
input_NetlistFreePES( p_spudec->bit_stream.p_input, DECODER_FIFO_START(p_spudec->fifo) );
DECODER_FIFO_INCSTART( p_spudec->fifo );
p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_spudec->p_fifo) );
DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
vlc_cond_wait( &p_spudec->p_fifo->data_wait, &p_spudec->p_fifo->data_lock );
}
/* We can release the lock before leaving */
vlc_mutex_unlock( &p_spudec->fifo.data_lock );
vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
}
/*****************************************************************************

View File

@ -37,9 +37,10 @@ typedef struct spudec_thread_s
/*
* Input properties
*/
decoder_fifo_t fifo; /* stores the PES stream data */
decoder_fifo_t * p_fifo; /* stores the PES stream data */
/* The bit stream structure handles the PES stream at the bit level */
bit_stream_t bit_stream;
vdec_config_t * p_config;
/*
* Decoder properties
@ -65,6 +66,5 @@ typedef struct spudec_thread_s
/*****************************************************************************
* Prototypes
*****************************************************************************/
spudec_thread_t * spudec_CreateThread( input_thread_t * p_input );
void spudec_DestroyThread( spudec_thread_t * p_spudec );
vlc_thread_t spudec_CreateThread( vdec_config_t * p_config );

View File

@ -36,8 +36,9 @@
#include "intf_msg.h"
#include "input.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"

View File

@ -38,8 +38,9 @@
#include "intf_msg.h"
#include "input.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"

View File

@ -38,8 +38,9 @@
#include "intf_msg.h"
#include "input.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"

View File

@ -38,8 +38,9 @@
#include "intf_msg.h"
#include "input.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"

View File

@ -39,8 +39,9 @@
#include "intf_msg.h"
#include "input.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"

View File

@ -37,9 +37,9 @@
#include "intf_msg.h"
#include "debug.h" /* XXX?? temporaire, requis par netlist.h */
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"

View File

@ -44,9 +44,9 @@
#include "intf_msg.h"
#include "debug.h" /* XXX?? temporaire, requis par netlist.h */
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"
@ -63,7 +63,6 @@
/*
* Local prototypes
*/
//static int CheckConfiguration ( video_cfg_t *p_cfg );
static int InitThread ( vpar_thread_t *p_vpar );
static void RunThread ( vpar_thread_t *p_vpar );
static void ErrorThread ( vpar_thread_t *p_vpar );
@ -77,12 +76,7 @@ static void EndThread ( vpar_thread_t *p_vpar );
* Following configuration properties are used:
* XXX??
*****************************************************************************/
#include "main.h"
#include "interface.h"
extern main_t * p_main;
vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_input /*,
vout_thread_t *p_vout, int *pi_status */ )
vlc_thread_t vpar_CreateThread( vdec_config_t * p_config )
{
vpar_thread_t * p_vpar;
@ -93,7 +87,7 @@ vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
{
intf_ErrMsg( "vpar error: not enough memory "
"for vpar_CreateThread() to create the new thread\n");
return( NULL );
return( 0 );
}
/*
@ -101,24 +95,10 @@ vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
*/
p_vpar->b_die = 0;
p_vpar->b_error = 0;
p_vpar->p_fifo = p_config->decoder_config.p_decoder_fifo;
p_vpar->p_config = p_config;
/*
* Initialize the input properties
*/
/* Initialize the decoder fifo's data lock and conditional variable
* and set its buffer as empty */
vlc_mutex_init( &p_vpar->fifo.data_lock );
vlc_cond_init( &p_vpar->fifo.data_wait );
p_vpar->fifo.i_start = 0;
p_vpar->fifo.i_end = 0;
/* Initialize the bit stream structure */
p_vpar->bit_stream.p_input = p_input;
p_vpar->bit_stream.p_decoder_fifo = &p_vpar->fifo;
p_vpar->bit_stream.fifo.buffer = 0;
p_vpar->bit_stream.fifo.i_available = 0;
/* FIXME !!!!?? */
p_vpar->p_vout = p_main->p_intf->p_vout;
p_vpar->p_vout = p_config->p_vout;
/* Spawn the video parser thread */
if ( vlc_thread_create( &p_vpar->thread_id, "video parser",
@ -126,54 +106,15 @@ vpar_thread_t * vpar_CreateThread( /* video_cfg_t *p_cfg, */ input_thread_t *p_i
{
intf_ErrMsg("vpar error: can't spawn video parser thread\n");
free( p_vpar );
return( NULL );
return( 0 );
}
intf_DbgMsg("vpar debug: video parser thread (%p) created\n", p_vpar);
return( p_vpar );
}
/*****************************************************************************
* vpar_DestroyThread: destroy a generic parser thread
*****************************************************************************
* Destroy a terminated thread. This function will return 0 if the thread could
* be destroyed, and non 0 else. The last case probably means that the thread
* was still active, and another try may succeed.
*****************************************************************************/
void vpar_DestroyThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
{
intf_DbgMsg( "vpar debug: requesting termination of "
"video parser thread %p\n", p_vpar);
/* Ask thread to kill itself */
p_vpar->b_die = 1;
/* Make sure the parser thread leaves the GetByte() function */
vlc_mutex_lock( &(p_vpar->fifo.data_lock) );
vlc_cond_signal( &(p_vpar->fifo.data_wait) );
vlc_mutex_unlock( &(p_vpar->fifo.data_lock) );
/* Waiting for the parser thread to exit */
/* Remove this as soon as the "status" flag is implemented */
vlc_thread_join( p_vpar->thread_id );
return( p_vpar->thread_id );
}
/* following functions are local */
/*****************************************************************************
* CheckConfiguration: check vpar_CreateThread() configuration
*****************************************************************************
* Set default parameters where required. In DEBUG mode, check if configuration
* is valid.
*****************************************************************************/
#if 0
static int CheckConfiguration( video_cfg_t *p_cfg )
{
/* XXX?? */
return( 0 );
}
#endif
/*****************************************************************************
* InitThread: initialize vpar output thread
*****************************************************************************
@ -189,24 +130,8 @@ static int InitThread( vpar_thread_t *p_vpar )
intf_DbgMsg("vpar debug: initializing video parser thread %p\n", p_vpar);
/* Our first job is to initialize the bit stream structure with the
* beginning of the input stream */
vlc_mutex_lock( &p_vpar->fifo.data_lock );
while ( DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
{
if ( p_vpar->b_die )
{
vlc_mutex_unlock( &p_vpar->fifo.data_lock );
return( 1 );
}
vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
}
p_vpar->bit_stream.p_ts = DECODER_FIFO_START( p_vpar->fifo )->p_first_ts;
p_vpar->bit_stream.p_byte = p_vpar->bit_stream.p_ts->buffer
+ p_vpar->bit_stream.p_ts->i_payload_start;
p_vpar->bit_stream.p_end = p_vpar->bit_stream.p_ts->buffer
+ p_vpar->bit_stream.p_ts->i_payload_end;
vlc_mutex_unlock( &p_vpar->fifo.data_lock );
p_vpar->p_config->decoder_config.pf_init_bit_stream( &p_vpar->bit_stream,
p_vpar->p_config->decoder_config.p_decoder_fifo );
/* Initialize parsing data */
p_vpar->sequence.p_forward = NULL;
@ -310,12 +235,12 @@ static void RunThread( vpar_thread_t *p_vpar )
* Main loop - it is not executed if an error occured during
* initialization
*/
while( (!p_vpar->b_die) && (!p_vpar->b_error) )
while( (!p_vpar->p_fifo->b_die) && (!p_vpar->b_error) )
{
/* Find the next sequence header in the stream */
p_vpar->b_error = vpar_NextSequenceHeader( p_vpar );
while( (!p_vpar->b_die) && (!p_vpar->b_error) )
while( (!p_vpar->p_fifo->b_die) && (!p_vpar->b_error) )
{
#ifdef STATS
p_vpar->c_loops++;
@ -354,25 +279,25 @@ static void ErrorThread( vpar_thread_t *p_vpar )
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock( &p_vpar->fifo.data_lock );
vlc_mutex_lock( &p_vpar->p_fifo->data_lock );
/* Wait until a `die' order is sent */
while( !p_vpar->b_die )
while( !p_vpar->p_fifo->b_die )
{
/* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY(p_vpar->fifo) )
while( !DECODER_FIFO_ISEMPTY(*p_vpar->p_fifo) )
{
input_NetlistFreePES( p_vpar->bit_stream.p_input,
DECODER_FIFO_START(p_vpar->fifo) );
DECODER_FIFO_INCSTART( p_vpar->fifo );
p_vpar->p_fifo->pf_delete_pes( p_vpar->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_vpar->p_fifo) );
DECODER_FIFO_INCSTART( *p_vpar->p_fifo );
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait( &p_vpar->fifo.data_wait, &p_vpar->fifo.data_lock );
vlc_cond_wait( &p_vpar->p_fifo->data_wait, &p_vpar->p_fifo->data_lock );
}
/* We can release the lock before leaving */
vlc_mutex_unlock( &p_vpar->fifo.data_lock );
vlc_mutex_unlock( &p_vpar->p_fifo->data_lock );
}
/*****************************************************************************

View File

@ -40,9 +40,9 @@
#include "intf_msg.h"
#include "debug.h" /* XXX?? temporaire, requis par netlist.h */
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"
@ -652,7 +652,7 @@ static __inline__ void DecodeMPEG1NonIntra( vpar_thread_t * p_vpar,
i_coef = 0;
b_sign = 0;
for( i_parse = 0; !p_vpar->b_die; i_parse++ )
for( i_parse = 0; !p_vpar->p_fifo->b_die; i_parse++ )
{
i_code = ShowBits( &p_vpar->bit_stream, 16 );
if( i_code >= 16384 )
@ -810,7 +810,7 @@ static __inline__ void DecodeMPEG1Intra( vpar_thread_t * p_vpar,
i_coef = 0;
b_sign = 0;
for( i_parse = 1; !p_vpar->b_die/*i_parse < 64*/; i_parse++ )
for( i_parse = 1; !p_vpar->p_fifo->b_die/*i_parse < 64*/; i_parse++ )
{
i_code = ShowBits( &p_vpar->bit_stream, 16 );
/* We use 2 main tables for the coefficients */
@ -932,7 +932,7 @@ static __inline__ void DecodeMPEG2NonIntra( vpar_thread_t * p_vpar,
i_nc = 0;
i_coef = 0;
for( i_parse = 0; !p_vpar->b_die; i_parse++ )
for( i_parse = 0; !p_vpar->p_fifo->b_die; i_parse++ )
{
i_code = ShowBits( &p_vpar->bit_stream, 16 );
if( i_code >= 16384 )
@ -1078,7 +1078,7 @@ static __inline__ void DecodeMPEG2Intra( vpar_thread_t * p_vpar,
i_coef = 0;
b_vlc_intra = p_vpar->picture.b_intra_vlc_format;
for( i_parse = 1; !p_vpar->b_die/*i_parse < 64*/; i_parse++ )
for( i_parse = 1; !p_vpar->p_fifo->b_die/*i_parse < 64*/; i_parse++ )
{
i_code = ShowBits( &p_vpar->bit_stream, 16 );
/* We use 2 main tables for the coefficients */
@ -2283,8 +2283,9 @@ static __inline__ void SliceHeader( vpar_thread_t * p_vpar,
return;
}
}
while( ShowBits( &p_vpar->bit_stream, 23 ) && !p_vpar->b_die );
NextStartCode( p_vpar );
while( ShowBits( &p_vpar->bit_stream, 23 )
&& !p_vpar->p_fifo->b_die );
NextStartCode( &p_vpar->bit_stream );
}
/*****************************************************************************
@ -2295,13 +2296,13 @@ void vpar_PictureData( vpar_thread_t * p_vpar, int i_mb_base )
int i_mb_address = 0;
u32 i_dummy;
NextStartCode( p_vpar );
NextStartCode( &p_vpar->bit_stream );
while( ((p_vpar->picture.i_coding_type != I_CODING_TYPE
&& p_vpar->picture.i_coding_type != D_CODING_TYPE)
|| !p_vpar->picture.b_error)
&& i_mb_address < (p_vpar->sequence.i_mb_size
>> (p_vpar->picture.i_structure != FRAME_STRUCTURE))
&& !p_vpar->b_die )
&& !p_vpar->p_fifo->b_die )
{
if( ((i_dummy = ShowBits( &p_vpar->bit_stream, 32 ))
< SLICE_START_CODE_MIN) ||

View File

@ -38,8 +38,9 @@
#include "intf_msg.h"
#include "input.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"
@ -56,7 +57,7 @@
/*
* Local prototypes
*/
static __inline__ void NextStartCode( vpar_thread_t * p_vpar );
static __inline__ void NextStartCode( bit_stream_t * );
static void SequenceHeader( vpar_thread_t * p_vpar );
static void GroupHeader( vpar_thread_t * p_vpar );
static void PictureHeader( vpar_thread_t * p_vpar );
@ -264,9 +265,9 @@ static __inline__ void LinkMatrix( quant_matrix_t * p_matrix, int * pi_array )
*****************************************************************************/
int vpar_NextSequenceHeader( vpar_thread_t * p_vpar )
{
while( !p_vpar->b_die )
while( !p_vpar->p_fifo->b_die )
{
NextStartCode( p_vpar );
NextStartCode( &p_vpar->bit_stream );
if( ShowBits( &p_vpar->bit_stream, 32 ) == SEQUENCE_HEADER_CODE )
{
return 0;
@ -281,9 +282,9 @@ int vpar_NextSequenceHeader( vpar_thread_t * p_vpar )
*****************************************************************************/
int vpar_ParseHeader( vpar_thread_t * p_vpar )
{
while( !p_vpar->b_die )
while( !p_vpar->p_fifo->b_die )
{
NextStartCode( p_vpar );
NextStartCode( &p_vpar->bit_stream );
switch( GetBits32( &p_vpar->bit_stream ) )
{
case SEQUENCE_HEADER_CODE:
@ -389,7 +390,7 @@ static void SequenceHeader( vpar_thread_t * p_vpar )
/*
* Sequence Extension
*/
NextStartCode( p_vpar );
NextStartCode( &p_vpar->bit_stream );
if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
{
int i_dummy;
@ -520,7 +521,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
/*
* Picture Coding Extension
*/
NextStartCode( p_vpar );
NextStartCode( &p_vpar->bit_stream );
if( ShowBits( &p_vpar->bit_stream, 32 ) == EXTENSION_START_CODE )
{
/* Parse picture_coding_extension */
@ -673,7 +674,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
== NULL )
{
intf_DbgMsg("vpar debug: allocation error in vout_CreatePicture, delaying\n");
if( p_vpar->b_die || p_vpar->b_error )
if( p_vpar->p_fifo->b_die || p_vpar->b_error )
{
return;
}
@ -736,7 +737,7 @@ static void PictureHeader( vpar_thread_t * p_vpar )
vpar_PictureData( p_vpar, i_mb_base );
if( p_vpar->b_die || p_vpar->b_error )
if( p_vpar->p_fifo->b_die || p_vpar->b_error )
{
return;
}
@ -797,9 +798,9 @@ static void PictureHeader( vpar_thread_t * p_vpar )
*****************************************************************************/
static void ExtensionAndUserData( vpar_thread_t * p_vpar )
{
while( !p_vpar->b_die )
while( !p_vpar->p_fifo->b_die )
{
NextStartCode( p_vpar );
NextStartCode( &p_vpar->bit_stream );
switch( ShowBits( &p_vpar->bit_stream, 32 ) )
{
case EXTENSION_START_CODE:

View File

@ -108,8 +108,9 @@
#include "intf_msg.h"
#include "input.h"
#include "decoder_fifo.h"
#include "stream_control.h"
#include "input_ext-dec.h"
#include "video.h"
#include "video_output.h"
@ -151,7 +152,7 @@ void vpar_SynchroInit( vpar_thread_t * p_vpar )
memset( p_vpar->synchro.p_tau, 0, 4 * sizeof(mtime_t) );
memset( p_vpar->synchro.pi_meaningful, 0, 4 * sizeof(unsigned int) );
p_vpar->synchro.b_dropped_last = 0;
p_vpar->synchro.current_pts = mdate() + INPUT_PTS_DELAY;
p_vpar->synchro.current_pts = mdate() + DEFAULT_PTS_DELAY;
p_vpar->synchro.backward_pts = 0;
}