From 6a74f9fb994a0027d4a495cbf08b6845d1c4ff1d Mon Sep 17 00:00:00 2001 From: Christophe Massiot Date: Wed, 12 Dec 2001 11:18:38 +0000 Subject: [PATCH] Next Generation Buffer Manager, for PS plug-in. --- include/config.h.in | 3 + include/input_ext-dec.h | 6 +- include/input_ext-plugins.h | 355 ++++++++++++++++++++++++- plugins/mpeg_system/input_ps.c | 468 ++------------------------------- 4 files changed, 390 insertions(+), 442 deletions(-) diff --git a/include/config.h.in b/include/config.h.in index 38e0c5ce5d..f39baf8551 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -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" diff --git a/include/input_ext-dec.h b/include/input_ext-dec.h index 99b0d4be00..ae867f7e54 100644 --- a/include/input_ext-dec.h +++ b/include/input_ext-dec.h @@ -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 * Michel Kaempf @@ -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; /***************************************************************************** diff --git a/include/input_ext-plugins.h b/include/input_ext-plugins.h index c1049647eb..5eb3e3a074 100644 --- a/include/input_ext-plugins.h +++ b/include/input_ext-plugins.h @@ -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 * @@ -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 */ diff --git a/plugins/mpeg_system/input_ps.c b/plugins/mpeg_system/input_ps.c index 5f795c1299..242b9c3818 100644 --- a/plugins/mpeg_system/input_ps.c +++ b/plugins/mpeg_system/input_ps.c @@ -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 * Cyril Deguet @@ -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 ); -} -