Commit dc804fe5 authored by Christophe Massiot's avatar Christophe Massiot

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

parent d9cac7cd
......@@ -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) \
......
......@@ -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"
......
/*****************************************************************************
* 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 );
/* Structures exported to the decoders */
/*****************************************************************************
* decoder_fifo.h: interface for decoders PES fifo
* data_packet_t
*****************************************************************************
* 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.
* 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;
/*****************************************************************************
* Required headers:
* - "config.h"
* - "common.h"
* - "threads.h"
* - "input.h"
* 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 */
#define WORD_TYPE u32
#define WORD_BYTE_LENGTH 4
#define WORD_LENGTH 32
/* 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;
/*****************************************************************************
* Macros
* 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;
/* FIXME: move to inline functions ??*/
/* 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 )
......@@ -49,29 +83,14 @@
#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 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
......@@ -95,44 +114,52 @@ 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;
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 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;
/* 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;
byte_t * p_end;
/*
* Bit structures
*/
bit_fifo_t fifo;
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.
*/
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 ? */
/* 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 TS packet */
decoder_fifo_next( p_bit_stream );
/* no, switch to next data packet */
p_bit_stream->pf_next_data_packet( p_bit_stream );
}
return( *(p_bit_stream->p_byte++));
return( *(p_bit_stream->p_byte++) );
}
/*****************************************************************************
......@@ -151,7 +178,9 @@ 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.buffer |= ((WORD_TYPE)GetByte( p_bit_stream ))
<< (sizeof(WORD_TYPE) - 8
- p_bit_stream->fifo.i_available);
p_bit_stream->fifo.i_available += 8;
}
}
......@@ -168,62 +197,85 @@ static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int 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).
* 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.
*/
void PeekNextPacket( bit_stream_t * p_bit_stream );
#if (WORD_TYPE != u32)
# error Not supported word
#endif
//(stolen from the kernel)
// XXX: The macro swab32 for little endian machine does
// not seem to work correctly
/*
* 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)
# 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)
# 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;
}
# else
# define swab32(x)\
( ( (u32)(((u8*)&x)[0]) << 24 ) | ( (u32)(((u8*)&x)[1]) << 16 ) | \
# 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
# 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) ) );
}