mirror of https://code.videolan.org/videolan/vlc
The input-II. (more info by mail in about an hour)
This commit is contained in:
parent
d9cac7cd2a
commit
dc804fe5e1
15
Makefile.in
15
Makefile.in
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
385
include/input.h
385
include/input.h
|
@ -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 );
|
|
@ -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
|
|
@ -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 * );
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
1479
src/input/input.c
1479
src/input/input.c
File diff suppressed because it is too large
Load Diff
|
@ -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 * );
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
|
@ -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
|
@ -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 );
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -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 );
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
@ -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 );
|
|
@ -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 */
|
||||
}
|
|
@ -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;
|
|
@ -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
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 * );
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -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 );
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -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 );
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue