mirror of
https://code.videolan.org/videolan/vlc
synced 2024-09-04 09:11:33 +02:00
Next Generation Buffer Manager, for PS plug-in.
This commit is contained in:
parent
279f805ab1
commit
6a74f9fb99
@ -175,6 +175,9 @@
|
||||
/* Maximum length of a hostname or source name */
|
||||
#define INPUT_MAX_SOURCE_LENGTH 100
|
||||
|
||||
/* Maximum memory the input is allowed to use (20 MB) */
|
||||
#define INPUT_MAX_ALLOCATION 20971520
|
||||
|
||||
/* Default network protocol */
|
||||
#define INPUT_NETWORK_PROTOCOL_VAR "vlc_network_protocol"
|
||||
#define INPUT_NETWORK_PROTOCOL_DEFAULT "ts"
|
||||
|
@ -2,7 +2,7 @@
|
||||
* input_ext-dec.h: structures exported to the VideoLAN decoders
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000 VideoLAN
|
||||
* $Id: input_ext-dec.h,v 1.42 2001/12/10 04:53:10 sam Exp $
|
||||
* $Id: input_ext-dec.h,v 1.43 2001/12/12 11:18:38 massiot Exp $
|
||||
*
|
||||
* Authors: Christophe Massiot <massiot@via.ecp.fr>
|
||||
* Michel Kaempf <maxx@via.ecp.fr>
|
||||
@ -44,6 +44,7 @@ typedef struct data_packet_s
|
||||
{
|
||||
/* Nothing before this line, the code relies on that */
|
||||
byte_t * p_buffer; /* raw data packet */
|
||||
byte_t * p_buffer_end;
|
||||
long l_size; /* buffer size */
|
||||
|
||||
/* Decoders information */
|
||||
@ -83,6 +84,9 @@ typedef struct pes_packet_s
|
||||
p_next fields of the data_packet_t struct) */
|
||||
data_packet_t * p_first; /* The first packet contained by this
|
||||
* PES (used by decoders). */
|
||||
|
||||
/* Chained list used by the input buffers manager */
|
||||
struct pes_packet_s * p_next;
|
||||
} pes_packet_t;
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -3,7 +3,7 @@
|
||||
* but exported to plug-ins
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: input_ext-plugins.h,v 1.8 2001/12/10 04:53:10 sam Exp $
|
||||
* $Id: input_ext-plugins.h,v 1.9 2001/12/12 11:18:38 massiot Exp $
|
||||
*
|
||||
* Authors: Christophe Massiot <massiot@via.ecp.fr>
|
||||
*
|
||||
@ -197,6 +197,359 @@ void input_NetlistDeletePES( void *,
|
||||
void input_NetlistEnd( struct input_thread_s * );
|
||||
|
||||
|
||||
/*
|
||||
* Optional Next Generation buffer manager
|
||||
*
|
||||
* Either buffers can only be used in one data packet (PS case), or buffers
|
||||
* contain several data packets (DVD case). In the first case, buffers are
|
||||
* embedded into data packets, otherwise they are allocated separately and
|
||||
* shared with a refcount. --Meuuh
|
||||
*/
|
||||
|
||||
/* Number of buffers for the calculation of the mean */
|
||||
#define INPUT_BRESENHAM_NB 50
|
||||
|
||||
/* Flags */
|
||||
#define BUFFERS_NOFLAGS 0
|
||||
#define BUFFERS_SHARED 1
|
||||
#define BUFFERS_UNIQUE_SIZE 2
|
||||
|
||||
/*****************************************************************************
|
||||
* input_buffers_t: defines a LIFO per data type to keep
|
||||
*****************************************************************************/
|
||||
#define PACKETS_LIFO( TYPE, NAME ) \
|
||||
struct \
|
||||
{ \
|
||||
TYPE * p_stack; \
|
||||
unsigned int i_depth; \
|
||||
} NAME;
|
||||
|
||||
#define BUFFERS_LIFO( TYPE, NAME ) \
|
||||
struct \
|
||||
{ \
|
||||
TYPE * p_stack; /* First item in the LIFO */ \
|
||||
unsigned int i_depth; /* Number of items in the LIFO */ \
|
||||
unsigned int i_average_size; /* Average size of the items (Bresenham) */\
|
||||
} NAME;
|
||||
|
||||
#define DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO ) \
|
||||
typedef struct input_buffers_s \
|
||||
{ \
|
||||
vlc_mutex_t lock; \
|
||||
PACKETS_LIFO( pes_packet_t, pes ) \
|
||||
BUFFERS_LIFO( data_packet_t, data[NB_LIFO] ) \
|
||||
size_t i_allocated; \
|
||||
} input_buffers_t;
|
||||
|
||||
#define DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ) \
|
||||
typedef struct data_buffer_s \
|
||||
{ \
|
||||
int i_refcount; \
|
||||
int i_size; \
|
||||
struct data_buffers_s * p_next; \
|
||||
byte_t payload_start; \
|
||||
} data_buffer_t; \
|
||||
\
|
||||
typedef struct input_buffers_s \
|
||||
{ \
|
||||
vlc_mutex_t lock; \
|
||||
PACKETS_LIFO( pes_packet_t, pes ) \
|
||||
PACKETS_LIFO( data_packet_t, data ) \
|
||||
BUFFERS_LIFO( data_buffers_t, buffers[NB_LIFO] ) \
|
||||
size_t i_allocated; \
|
||||
} input_buffers_t;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* input_BuffersInit: initialize the cache structures, return a pointer to it
|
||||
*****************************************************************************/
|
||||
#define DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO ) \
|
||||
static void * input_BuffersInit( void ) \
|
||||
{ \
|
||||
input_buffers_t * p_buffers = malloc( sizeof( input_buffers_t ) ); \
|
||||
\
|
||||
if( p_buffers == NULL ) \
|
||||
{ \
|
||||
return( NULL ); \
|
||||
} \
|
||||
\
|
||||
memset( p_buffers, 0, sizeof( input_buffers_t ) ); \
|
||||
vlc_mutex_init( &p_buffers->lock ); \
|
||||
\
|
||||
return (void *)p_buffers; \
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* input_BuffersEnd: free all cached structures
|
||||
*****************************************************************************/
|
||||
#define DECLARE_BUFFERS_END( FLAGS, NB_LIFO ) \
|
||||
static void input_BuffersEnd( void * _p_buffers ) \
|
||||
{ \
|
||||
input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
|
||||
\
|
||||
if( _p_buffers != NULL ) \
|
||||
{ \
|
||||
pes_packet_t * p_pes = p_buffers->pes.p_stack; \
|
||||
int i; \
|
||||
\
|
||||
if( p_main->b_stats ) \
|
||||
{ \
|
||||
int i; \
|
||||
for( i = 0; i < NB_LIFO; i++ ) \
|
||||
{ \
|
||||
intf_StatMsg( \
|
||||
"input buffers stats: data[%d]: %d bytes, %d packets", \
|
||||
i, p_buffers->data[i].i_average_size, \
|
||||
p_buffers->data[i].i_depth ); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* Free PES */ \
|
||||
while( p_pes != NULL ) \
|
||||
{ \
|
||||
pes_packet_t * p_next = p_pes->p_next; \
|
||||
free( p_pes ); \
|
||||
p_pes = p_next; \
|
||||
} \
|
||||
\
|
||||
for( i = 0; i < NB_LIFO; i++ ) \
|
||||
{ \
|
||||
data_packet_t * p_data = p_buffers->data[i].p_stack; \
|
||||
\
|
||||
/* Free data packets */ \
|
||||
while( p_data != NULL ) \
|
||||
{ \
|
||||
data_packet_t * p_next = p_data->p_next; \
|
||||
p_buffers->i_allocated -= p_data->p_buffer_end \
|
||||
- p_data->p_buffer; \
|
||||
free( p_data ); \
|
||||
p_data = p_next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if( p_buffers->i_allocated ) \
|
||||
{ \
|
||||
intf_ErrMsg( "input buffers error: %d bytes have not been" \
|
||||
" freed, expect memory leak", \
|
||||
p_buffers->i_allocated ); \
|
||||
} \
|
||||
\
|
||||
vlc_mutex_destroy( &p_buffers->lock ); \
|
||||
free( _p_buffers ); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* input_NewPacket: return a pointer to a data packet of the appropriate size
|
||||
*****************************************************************************/
|
||||
#define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ) \
|
||||
static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \
|
||||
{ \
|
||||
input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
|
||||
int i_select; \
|
||||
data_packet_t * p_data; \
|
||||
\
|
||||
/* Safety checks */ \
|
||||
if( i_size > INPUT_MAX_PACKET_SIZE ) \
|
||||
{ \
|
||||
intf_ErrMsg( "Packet too big (%d)", i_size ); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
vlc_mutex_lock( &p_buffers->lock ); \
|
||||
\
|
||||
if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION ) \
|
||||
{ \
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)", \
|
||||
p_buffers->i_allocated ); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
|
||||
{ \
|
||||
if( i_size <= (2 * p_buffers->data[i_select].i_average_size \
|
||||
+ p_buffers->data[i_select + 1].i_average_size) / 3 ) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if( p_buffers->data[i_select].p_stack != NULL ) \
|
||||
{ \
|
||||
/* Take the packet from the cache */ \
|
||||
p_data = p_buffers->data[i_select].p_stack; \
|
||||
p_buffers->data[i_select].p_stack = p_data->p_next; \
|
||||
p_buffers->data[i_select].i_depth--; \
|
||||
\
|
||||
/* Reallocate the packet if it is too small or too large */ \
|
||||
if( p_data->p_buffer_end - p_data->p_buffer < i_size || \
|
||||
p_data->p_buffer_end - p_data->p_buffer > 3 * i_size ) \
|
||||
{ \
|
||||
p_buffers->i_allocated -= p_data->p_buffer_end \
|
||||
- p_data->p_buffer; \
|
||||
p_data = realloc( p_data, sizeof( data_packet_t ) + i_size ); \
|
||||
if( p_data == NULL ) \
|
||||
{ \
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
intf_ErrMsg( "Out of memory" ); \
|
||||
return NULL; \
|
||||
} \
|
||||
p_data->p_buffer = (byte_t *)p_data + sizeof( data_packet_t ); \
|
||||
p_data->p_buffer_end = p_data->p_buffer + i_size; \
|
||||
p_buffers->i_allocated += i_size; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Allocate a new packet */ \
|
||||
p_data = malloc( sizeof( data_packet_t ) + i_size ); \
|
||||
if( p_data == NULL ) \
|
||||
{ \
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
intf_ErrMsg( "Out of memory" ); \
|
||||
return NULL; \
|
||||
} \
|
||||
p_data->p_buffer = (byte_t *)p_data + sizeof( data_packet_t ); \
|
||||
p_data->p_buffer_end = p_data->p_buffer + i_size; \
|
||||
p_buffers->i_allocated += i_size; \
|
||||
} \
|
||||
\
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
\
|
||||
/* Initialize data */ \
|
||||
p_data->p_next = NULL; \
|
||||
p_data->b_discard_payload = 0; \
|
||||
p_data->p_payload_start = p_data->p_buffer; \
|
||||
p_data->p_payload_end = p_data->p_buffer + i_size; \
|
||||
\
|
||||
return( p_data ); \
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* input_DeletePacket: put a packet back into the cache
|
||||
*****************************************************************************/
|
||||
#define DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
|
||||
static __inline__ void _input_DeletePacket( void * _p_buffers, \
|
||||
data_packet_t * p_data ) \
|
||||
{ \
|
||||
input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
|
||||
int i_select, i_size; \
|
||||
\
|
||||
i_size = p_data->p_buffer_end - p_data->p_buffer; \
|
||||
for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
|
||||
{ \
|
||||
if( i_size <= (2 * p_buffers->data[i_select].i_average_size \
|
||||
+ p_buffers->data[i_select + 1].i_average_size) / 3 ) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if( p_buffers->data[i_select].i_depth < DATA_CACHE_SIZE ) \
|
||||
{ \
|
||||
/* Cache not full : store the packet in it */ \
|
||||
p_data->p_next = p_buffers->data[i_select].p_stack; \
|
||||
p_buffers->data[i_select].p_stack = p_data; \
|
||||
p_buffers->data[i_select].i_depth++; \
|
||||
\
|
||||
/* Update Bresenham mean (very approximative) */ \
|
||||
p_buffers->data[i_select].i_average_size = ( i_size \
|
||||
+ p_buffers->data[i_select].i_average_size \
|
||||
* (INPUT_BRESENHAM_NB - 1) ) \
|
||||
/ INPUT_BRESENHAM_NB; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
p_buffers->i_allocated -= p_data->p_buffer_end - p_data->p_buffer; \
|
||||
free( p_data ); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static void input_DeletePacket( void * _p_buffers, data_packet_t * p_data ) \
|
||||
{ \
|
||||
input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
|
||||
\
|
||||
vlc_mutex_lock( &p_buffers->lock ); \
|
||||
_input_DeletePacket( _p_buffers, p_data ); \
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* input_NewPES: return a pointer to a new PES packet
|
||||
*****************************************************************************/
|
||||
#define DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ) \
|
||||
static pes_packet_t * input_NewPES( void * _p_buffers ) \
|
||||
{ \
|
||||
input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
|
||||
pes_packet_t * p_pes; \
|
||||
\
|
||||
vlc_mutex_lock( &p_buffers->lock ); \
|
||||
\
|
||||
if( p_buffers->pes.p_stack != NULL ) \
|
||||
{ \
|
||||
p_pes = p_buffers->pes.p_stack; \
|
||||
p_buffers->pes.p_stack = p_pes->p_next; \
|
||||
p_buffers->pes.i_depth--; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
p_pes = malloc( sizeof( pes_packet_t ) ); \
|
||||
if( p_pes == NULL ) \
|
||||
{ \
|
||||
intf_ErrMsg( "Out of memory" ); \
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
return( NULL ); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
\
|
||||
/* Initialize data */ \
|
||||
p_pes->p_next = NULL; \
|
||||
p_pes->b_data_alignment = p_pes->b_discontinuity = \
|
||||
p_pes->i_pts = p_pes->i_dts = 0; \
|
||||
p_pes->i_pes_size = 0; \
|
||||
p_pes->p_first = NULL; \
|
||||
\
|
||||
return( p_pes ); \
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* input_DeletePES: put a pes and all data packets back into the cache
|
||||
*****************************************************************************/
|
||||
#define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, PES_CACHE_SIZE ) \
|
||||
static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes ) \
|
||||
{ \
|
||||
input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
|
||||
data_packet_t * p_data; \
|
||||
\
|
||||
vlc_mutex_lock( &p_buffers->lock ); \
|
||||
\
|
||||
p_data = p_pes->p_first; \
|
||||
while( p_data != NULL ) \
|
||||
{ \
|
||||
data_packet_t * p_next = p_data->p_next; \
|
||||
_input_DeletePacket( _p_buffers, p_data ); \
|
||||
p_data = p_next; \
|
||||
} \
|
||||
\
|
||||
if( p_buffers->pes.i_depth < PES_CACHE_SIZE ) \
|
||||
{ \
|
||||
/* Cache not full : store the packet in it */ \
|
||||
p_pes->p_next = p_buffers->pes.p_stack; \
|
||||
p_buffers->pes.p_stack = p_pes; \
|
||||
p_buffers->pes.i_depth++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
free( p_pes ); \
|
||||
} \
|
||||
\
|
||||
vlc_mutex_unlock( &p_buffers->lock ); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Optional MPEG demultiplexing
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@
|
||||
* input_ps.c: PS demux and packet management
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1998-2001 VideoLAN
|
||||
* $Id: input_ps.c,v 1.2 2001/12/10 04:53:11 sam Exp $
|
||||
* $Id: input_ps.c,v 1.3 2001/12/12 11:18:38 massiot Exp $
|
||||
*
|
||||
* Authors: Christophe Massiot <massiot@via.ecp.fr>
|
||||
* Cyril Deguet <asmax@via.ecp.fr>
|
||||
@ -91,10 +91,20 @@ static void PSInit ( struct input_thread_s * );
|
||||
static void PSEnd ( struct input_thread_s * );
|
||||
static int PSSetProgram ( struct input_thread_s * , pgrm_descriptor_t * );
|
||||
static void PSSeek ( struct input_thread_s *, off_t );
|
||||
static struct pes_packet_s * NewPES ( void * );
|
||||
static struct data_packet_s * NewPacket ( void *, size_t );
|
||||
static void DeletePacket ( void *, struct data_packet_s * );
|
||||
static void DeletePES ( void *, struct pes_packet_s * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Declare a buffer manager
|
||||
*****************************************************************************/
|
||||
#define FLAGS BUFFERS_NOFLAGS
|
||||
#define NB_LIFO 2
|
||||
DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
|
||||
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
|
||||
DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
|
||||
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
|
||||
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
|
||||
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
|
||||
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Functions exported as capabilities. They are declared as static so that
|
||||
@ -113,10 +123,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
|
||||
input.pf_set_program = PSSetProgram;
|
||||
input.pf_read = PSRead;
|
||||
input.pf_demux = input_DemuxPS;
|
||||
input.pf_new_packet = NewPacket;
|
||||
input.pf_new_pes = NewPES;
|
||||
input.pf_delete_packet = DeletePacket;
|
||||
input.pf_delete_pes = DeletePES;
|
||||
input.pf_new_packet = input_NewPacket;
|
||||
input.pf_new_pes = input_NewPES;
|
||||
input.pf_delete_packet = input_DeletePacket;
|
||||
input.pf_delete_pes = input_DeletePES;
|
||||
input.pf_rewind = NULL;
|
||||
input.pf_seek = PSSeek;
|
||||
#undef input
|
||||
@ -158,65 +168,12 @@ static int PSProbe( probedata_t *p_data )
|
||||
*****************************************************************************/
|
||||
static void PSInit( input_thread_t * p_input )
|
||||
{
|
||||
packet_cache_t * p_packet_cache;
|
||||
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
|
||||
{
|
||||
p_input->b_error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* creates the packet cache structure */
|
||||
p_packet_cache = malloc( sizeof(packet_cache_t) );
|
||||
if ( p_packet_cache == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
p_input->b_error = 1;
|
||||
return;
|
||||
}
|
||||
p_input->p_method_data = (void *)p_packet_cache;
|
||||
|
||||
/* Initialize packet cache mutex */
|
||||
vlc_mutex_init( &p_packet_cache->lock );
|
||||
|
||||
/* allocates the data cache */
|
||||
p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE *
|
||||
sizeof(data_packet_t*) );
|
||||
if ( p_packet_cache->data.p_stack == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
p_input->b_error = 1;
|
||||
return;
|
||||
}
|
||||
p_packet_cache->data.l_index = 0;
|
||||
|
||||
/* allocates the PES cache */
|
||||
p_packet_cache->pes.p_stack = malloc( PES_CACHE_SIZE *
|
||||
sizeof(pes_packet_t*) );
|
||||
if ( p_packet_cache->pes.p_stack == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
p_input->b_error = 1;
|
||||
return;
|
||||
}
|
||||
p_packet_cache->pes.l_index = 0;
|
||||
|
||||
/* allocates the small buffer cache */
|
||||
p_packet_cache->smallbuffer.p_stack = malloc( SMALL_CACHE_SIZE *
|
||||
sizeof(packet_buffer_t) );
|
||||
if ( p_packet_cache->smallbuffer.p_stack == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
p_input->b_error = 1;
|
||||
return;
|
||||
}
|
||||
p_packet_cache->smallbuffer.l_index = 0;
|
||||
|
||||
/* allocates the large buffer cache */
|
||||
p_packet_cache->largebuffer.p_stack = malloc( LARGE_CACHE_SIZE *
|
||||
sizeof(packet_buffer_t) );
|
||||
if ( p_packet_cache->largebuffer.p_stack == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
p_input->b_error = 1;
|
||||
return;
|
||||
}
|
||||
p_packet_cache->largebuffer.l_index = 0;
|
||||
|
||||
if( p_input->p_stream == NULL )
|
||||
{
|
||||
/* Re-open the socket as a buffered FILE stream */
|
||||
@ -275,7 +232,7 @@ static void PSInit( input_thread_t * p_input )
|
||||
{
|
||||
/* FIXME: use i_p_config_t */
|
||||
input_ParsePS( p_input, pp_packets[i] );
|
||||
DeletePacket( p_input->p_method_data, pp_packets[i] );
|
||||
p_input->pf_delete_packet( p_input->p_method_data, pp_packets[i] );
|
||||
}
|
||||
|
||||
/* File too big. */
|
||||
@ -388,22 +345,7 @@ static void PSInit( input_thread_t * p_input )
|
||||
*****************************************************************************/
|
||||
static void PSEnd( input_thread_t * p_input )
|
||||
{
|
||||
#define p_packet_cache ((packet_cache_t *)p_input->p_method_data)
|
||||
|
||||
vlc_mutex_destroy( &p_packet_cache->lock );
|
||||
|
||||
if( p_packet_cache->data.p_stack )
|
||||
free( p_packet_cache->data.p_stack );
|
||||
if( p_packet_cache->pes.p_stack )
|
||||
free( p_packet_cache->pes.p_stack );
|
||||
if( p_packet_cache->smallbuffer.p_stack )
|
||||
free( p_packet_cache->smallbuffer.p_stack );
|
||||
if( p_packet_cache->largebuffer.p_stack )
|
||||
free( p_packet_cache->largebuffer.p_stack );
|
||||
|
||||
#undef p_packet_cache
|
||||
|
||||
free( p_input->p_method_data );
|
||||
input_BuffersEnd( p_input->p_method_data );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -528,7 +470,8 @@ static int PSRead( input_thread_t * p_input,
|
||||
}
|
||||
|
||||
/* Fetch a packet of the appropriate size. */
|
||||
p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 );
|
||||
p_data = p_input->pf_new_packet( p_input->p_method_data,
|
||||
i_packet_size + 6 );
|
||||
if( p_data == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
@ -598,358 +541,3 @@ static void PSSeek( input_thread_t * p_input, off_t i_position )
|
||||
p_input->stream.p_selected_area->i_tell = i_position;
|
||||
}
|
||||
|
||||
/*
|
||||
* Packet management utilities
|
||||
*/
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* NewPacket: allocates a data packet
|
||||
*****************************************************************************/
|
||||
static struct data_packet_s * NewPacket( void * p_packet_cache,
|
||||
size_t l_size )
|
||||
{
|
||||
packet_cache_t * p_cache;
|
||||
data_packet_t * p_data;
|
||||
long l_index;
|
||||
|
||||
p_cache = (packet_cache_t *)p_packet_cache;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( p_cache == NULL )
|
||||
{
|
||||
intf_ErrMsg( "PPacket cache not initialized" );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Safety check */
|
||||
if( l_size > INPUT_MAX_PACKET_SIZE )
|
||||
{
|
||||
intf_ErrMsg( "Packet too big (%d)", l_size );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vlc_mutex_lock( &p_cache->lock );
|
||||
|
||||
/* Checks whether the data cache is empty */
|
||||
if( p_cache->data.l_index == 0 )
|
||||
{
|
||||
/* Allocates a new packet */
|
||||
p_data = malloc( sizeof(data_packet_t) );
|
||||
if( p_data == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: data packet allocated" );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Takes the packet out from the cache */
|
||||
if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ])
|
||||
== NULL )
|
||||
{
|
||||
intf_ErrMsg( "NULL packet in the data cache" );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( l_size < MAX_SMALL_SIZE )
|
||||
{
|
||||
/* Small buffer */
|
||||
|
||||
/* Checks whether the buffer cache is empty */
|
||||
if( p_cache->smallbuffer.l_index == 0 )
|
||||
{
|
||||
/* Allocates a new packet */
|
||||
p_data->p_buffer = malloc( l_size );
|
||||
if( p_data->p_buffer == NULL )
|
||||
{
|
||||
intf_DbgMsg( "Out of memory" );
|
||||
free( p_data );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: small buffer allocated" );
|
||||
#endif
|
||||
p_data->l_size = l_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Takes the packet out from the cache */
|
||||
l_index = -- p_cache->smallbuffer.l_index;
|
||||
if( (p_data->p_buffer = p_cache->smallbuffer.p_stack[l_index].p_data)
|
||||
== NULL )
|
||||
{
|
||||
intf_ErrMsg( "NULL packet in the small buffer cache" );
|
||||
free( p_data );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
/* Reallocates the packet if it is too small or too large */
|
||||
if( p_cache->smallbuffer.p_stack[l_index].l_size < l_size ||
|
||||
p_cache->smallbuffer.p_stack[l_index].l_size > 2*l_size )
|
||||
{
|
||||
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
|
||||
p_data->l_size = l_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_data->l_size = p_cache->smallbuffer.p_stack[l_index].l_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Large buffer */
|
||||
|
||||
/* Checks whether the buffer cache is empty */
|
||||
if( p_cache->largebuffer.l_index == 0 )
|
||||
{
|
||||
/* Allocates a new packet */
|
||||
p_data->p_buffer = malloc( l_size );
|
||||
if ( p_data->p_buffer == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Out of memory" );
|
||||
free( p_data );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: large buffer allocated" );
|
||||
#endif
|
||||
p_data->l_size = l_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Takes the packet out from the cache */
|
||||
l_index = -- p_cache->largebuffer.l_index;
|
||||
p_data->p_buffer = p_cache->largebuffer.p_stack[l_index].p_data;
|
||||
if( p_data->p_buffer == NULL )
|
||||
{
|
||||
intf_ErrMsg( "NULL packet in the small buffer cache" );
|
||||
free( p_data );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
/* Reallocates the packet if it is too small or too large */
|
||||
if( p_cache->largebuffer.p_stack[l_index].l_size < l_size ||
|
||||
p_cache->largebuffer.p_stack[l_index].l_size > 2*l_size )
|
||||
{
|
||||
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
|
||||
p_data->l_size = l_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_data->l_size = p_cache->largebuffer.p_stack[l_index].l_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
|
||||
/* Initialize data */
|
||||
p_data->p_next = NULL;
|
||||
p_data->b_discard_payload = 0;
|
||||
p_data->p_payload_start = p_data->p_buffer;
|
||||
p_data->p_payload_end = p_data->p_buffer + l_size;
|
||||
|
||||
return( p_data );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* NewPES: allocates a pes packet
|
||||
*****************************************************************************/
|
||||
static pes_packet_t * NewPES( void * p_packet_cache )
|
||||
{
|
||||
packet_cache_t * p_cache;
|
||||
pes_packet_t * p_pes;
|
||||
|
||||
p_cache = (packet_cache_t *)p_packet_cache;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( p_cache == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Packet cache not initialized" );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
vlc_mutex_lock( &p_cache->lock );
|
||||
|
||||
/* Checks whether the PES cache is empty */
|
||||
if( p_cache->pes.l_index == 0 )
|
||||
{
|
||||
/* Allocates a new packet */
|
||||
p_pes = malloc( sizeof(pes_packet_t) );
|
||||
if( p_pes == NULL )
|
||||
{
|
||||
intf_DbgMsg( "Out of memory" );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: PES packet allocated" );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Takes the packet out from the cache */
|
||||
p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ];
|
||||
if( p_pes == NULL )
|
||||
{
|
||||
intf_ErrMsg( "NULL packet in the data cache" );
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
|
||||
p_pes->b_data_alignment = p_pes->b_discontinuity =
|
||||
p_pes->i_pts = p_pes->i_dts = 0;
|
||||
p_pes->i_pes_size = 0;
|
||||
p_pes->p_first = NULL;
|
||||
|
||||
return( p_pes );
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DeletePacket: deletes a data packet
|
||||
*****************************************************************************/
|
||||
static void DeletePacket( void * p_packet_cache,
|
||||
data_packet_t * p_data )
|
||||
{
|
||||
packet_cache_t * p_cache;
|
||||
|
||||
p_cache = (packet_cache_t *)p_packet_cache;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( p_cache == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Packet cache not initialized" );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSERT( p_data );
|
||||
|
||||
vlc_mutex_lock( &p_cache->lock );
|
||||
|
||||
/* Checks whether the data cache is full */
|
||||
if ( p_cache->data.l_index < DATA_CACHE_SIZE )
|
||||
{
|
||||
/* Cache not full: store the packet in it */
|
||||
p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
|
||||
/* Small buffer or large buffer? */
|
||||
if ( p_data->l_size < MAX_SMALL_SIZE )
|
||||
{
|
||||
/* Checks whether the small buffer cache is full */
|
||||
if ( p_cache->smallbuffer.l_index < SMALL_CACHE_SIZE )
|
||||
{
|
||||
p_cache->smallbuffer.p_stack[
|
||||
p_cache->smallbuffer.l_index ].l_size = p_data->l_size;
|
||||
p_cache->smallbuffer.p_stack[
|
||||
p_cache->smallbuffer.l_index++ ].p_data = p_data->p_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT( p_data->p_buffer );
|
||||
free( p_data->p_buffer );
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: small buffer freed" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Checks whether the large buffer cache is full */
|
||||
if ( p_cache->largebuffer.l_index < LARGE_CACHE_SIZE )
|
||||
{
|
||||
p_cache->largebuffer.p_stack[
|
||||
p_cache->largebuffer.l_index ].l_size = p_data->l_size;
|
||||
p_cache->largebuffer.p_stack[
|
||||
p_cache->largebuffer.l_index++ ].p_data = p_data->p_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT( p_data->p_buffer );
|
||||
free( p_data->p_buffer );
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: large buffer freed" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Cache full: the packet must be freed */
|
||||
free( p_data->p_buffer );
|
||||
free( p_data );
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: data packet freed" );
|
||||
#endif
|
||||
}
|
||||
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DeletePES: deletes a PES packet and associated data packets
|
||||
*****************************************************************************/
|
||||
static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
|
||||
{
|
||||
packet_cache_t * p_cache;
|
||||
data_packet_t * p_data;
|
||||
data_packet_t * p_next;
|
||||
|
||||
p_cache = (packet_cache_t *)p_packet_cache;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( p_cache == NULL )
|
||||
{
|
||||
intf_ErrMsg( "Packet cache not initialized" );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSERT( p_pes);
|
||||
|
||||
p_data = p_pes->p_first;
|
||||
|
||||
while( p_data != NULL )
|
||||
{
|
||||
p_next = p_data->p_next;
|
||||
DeletePacket( p_cache, p_data );
|
||||
p_data = p_next;
|
||||
}
|
||||
|
||||
vlc_mutex_lock( &p_cache->lock );
|
||||
|
||||
/* Checks whether the PES cache is full */
|
||||
if ( p_cache->pes.l_index < PES_CACHE_SIZE )
|
||||
{
|
||||
/* Cache not full: store the packet in it */
|
||||
p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Cache full: the packet must be freed */
|
||||
free( p_pes );
|
||||
#ifdef TRACE_INPUT
|
||||
intf_DbgMsg( "PS input: PES packet freed" );
|
||||
#endif
|
||||
}
|
||||
|
||||
vlc_mutex_unlock( &p_cache->lock );
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user