X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=plugins%2Fmpeg%2Finput_ps.c;h=d9df981630c183f907915bfffa5ea9bfe5e0ce9f;hb=abe5a7d0c0d40422c71bb4bebec73e4833600367;hp=a1ac8df8ab44273fe8cd544b1da4576cd00f1f0d;hpb=f3f860ca5d69aa95060c073fa912f653478d35b6;p=vlc diff --git a/plugins/mpeg/input_ps.c b/plugins/mpeg/input_ps.c index a1ac8df8ab..d9df981630 100644 --- a/plugins/mpeg/input_ps.c +++ b/plugins/mpeg/input_ps.c @@ -2,7 +2,7 @@ * input_ps.c: PS demux and packet management ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: input_ps.c,v 1.13 2001/04/05 16:37:15 asmax Exp $ + * $Id: input_ps.c,v 1.23 2001/05/08 00:43:57 sam Exp $ * * Authors: Christophe Massiot * Cyril Deguet @@ -32,6 +32,9 @@ #include #include +#ifdef STRNCASECMP_IN_STRINGS_H +# include +#endif #include #include @@ -143,6 +146,7 @@ static int PSProbe( probedata_t *p_data ) static void PSInit( input_thread_t * p_input ) { thread_ps_data_t * p_method; + packet_cache_t * p_packet_cache; if( (p_method = (thread_ps_data_t *)malloc( sizeof(thread_ps_data_t) )) == NULL ) @@ -151,10 +155,65 @@ static void PSInit( input_thread_t * p_input ) p_input->b_error = 1; return; } - p_input->p_plugin_data = (void *)p_method; - p_input->p_method_data = NULL; - + + /* 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->small.p_stack = malloc( SMALL_CACHE_SIZE * + sizeof(packet_buffer_t) ); + if ( p_packet_cache->small.p_stack == NULL ) + { + intf_ErrMsg( "Out of memory" ); + p_input->b_error = 1; + return; + } + p_packet_cache->small.l_index = 0; + + /* allocates the large buffer cache */ + p_packet_cache->large.p_stack = malloc( LARGE_CACHE_SIZE * + sizeof(packet_buffer_t) ); + if ( p_packet_cache->large.p_stack == NULL ) + { + intf_ErrMsg( "Out of memory" ); + p_input->b_error = 1; + return; + } + p_packet_cache->large.l_index = 0; + /* Re-open the socket as a buffered FILE stream */ if( (p_method->stream = fdopen( p_input->i_handle, "r" )) == NULL ) { @@ -214,7 +273,10 @@ static void PSInit( input_thread_t * p_input ) } rewind( p_method->stream ); vlc_mutex_lock( &p_input->stream.stream_lock ); + + p_input->stream.i_method = INPUT_METHOD_FILE; p_input->stream.p_selected_area->i_tell = 0; + if( p_demux_data->b_has_PSM ) { /* (The PSM decoder will care about spawning the decoders) */ @@ -292,6 +354,7 @@ static void PSInit( input_thread_t * p_input ) { /* The programs will be added when we read them. */ vlc_mutex_lock( &p_input->stream.stream_lock ); + p_input->stream.i_method = INPUT_METHOD_FILE; p_input->stream.pp_programs[0]->b_is_ok = 0; vlc_mutex_unlock( &p_input->stream.stream_lock ); } @@ -302,6 +365,7 @@ static void PSInit( input_thread_t * p_input ) *****************************************************************************/ static void PSEnd( input_thread_t * p_input ) { + vlc_mutex_destroy( &((packet_cache_t *)p_input->p_plugin_data)->lock ); free( p_input->p_plugin_data ); } @@ -372,7 +436,7 @@ static int PSRead( input_thread_t * p_input, /* It is common for MPEG-1 streams to pad with zeros * (although it is forbidden by the recommendation), so * don't bother everybody in this case. */ - intf_WarnMsg( 1, "Garbage at input (%.8x)", i_startcode ); + intf_WarnMsg( 3, "Garbage at input (%.8x)", i_startcode ); } while( (i_startcode & 0xFFFFFF00) != 0x100L ) @@ -421,7 +485,8 @@ static int PSRead( input_thread_t * p_input, } /* Fetch a packet of the appropriate size. */ - if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL ) + if( (p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 )) + == NULL ) { intf_ErrMsg( "Out of memory" ); return( -1 ); @@ -469,7 +534,11 @@ static void PSSeek( input_thread_t * p_input, off_t i_position ) p_method = (thread_ps_data_t *)p_input->p_plugin_data; /* A little bourrin but should work for a while --Meuuh */ +#ifndef WIN32 fseeko( p_method->stream, i_position, SEEK_SET ); +#else + fseek( p_method->stream, (long)i_position, SEEK_SET ); +#endif p_input->stream.p_selected_area->i_tell = i_position; } @@ -482,53 +551,209 @@ static void PSSeek( input_thread_t * p_input, off_t i_position ) /***************************************************************************** * NewPacket: allocates a data packet *****************************************************************************/ -static struct data_packet_s * NewPacket( void * p_garbage, - size_t i_size ) -{ - data_packet_t * p_data; +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; - /* Safety check */ - if( i_size > INPUT_MAX_PACKET_SIZE ) + p_cache = (packet_cache_t *)p_packet_cache; + +#ifdef DEBUG + if ( p_cache == NULL ) { - intf_ErrMsg( "Packet too big (%d)", i_size ); + intf_ErrMsg( "PPacket cache not initialized" ); return NULL; } +#endif - if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL ) + /* Safety check */ + if( l_size > INPUT_MAX_PACKET_SIZE ) { - intf_DbgMsg( "Out of memory" ); + intf_ErrMsg( "Packet too big (%d)", l_size ); return NULL; } - if( (p_data->p_buffer = (byte_t *)malloc( i_size )) == NULL ) + vlc_mutex_lock( &p_cache->lock ); + + /* Checks whether the data cache is empty */ + if( p_cache->data.l_index == 0 ) { - intf_DbgMsg( "Out of memory" ); - free( p_data ); - return NULL; + /* Allocates a new packet */ + if ( (p_data = malloc( sizeof(data_packet_t) )) == 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->small.l_index == 0 ) + { + /* Allocates a new packet */ + if ( (p_data->p_buffer = malloc( l_size )) == 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->small.l_index; + if( (p_data->p_buffer = p_cache->small.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->small.p_stack[l_index].l_size < l_size || + p_cache->small.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->small.p_stack[l_index].l_size; + } + } + } + else + { + /* Large buffer */ + + /* Checks whether the buffer cache is empty */ + if( p_cache->large.l_index == 0 ) + { + /* Allocates a new packet */ + if ( (p_data->p_buffer = malloc( l_size )) == 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->large.l_index; + if( (p_data->p_buffer = p_cache->large.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->large.p_stack[l_index].l_size < l_size || + p_cache->large.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->large.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 + i_size; + 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_garbage ) +static pes_packet_t * NewPES( void * p_packet_cache ) { - pes_packet_t * p_pes; + packet_cache_t * p_cache; + pes_packet_t * p_pes; - if( (p_pes = (pes_packet_t *)malloc( sizeof(pes_packet_t) )) == NULL ) + p_cache = (packet_cache_t *)p_packet_cache; + +#ifdef DEBUG + if ( p_cache == NULL ) { - intf_DbgMsg( "Out of memory" ); + 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 */ + if ( (p_pes = malloc( sizeof(pes_packet_t) )) == 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 */ + if( (p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ]) + == 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; @@ -536,38 +761,136 @@ static pes_packet_t * NewPES( void * p_garbage ) p_pes->p_first = NULL; return( p_pes ); + } /***************************************************************************** * DeletePacket: deletes a data packet *****************************************************************************/ -static void DeletePacket( void * p_garbage, +static void DeletePacket( void * p_packet_cache, data_packet_t * p_data ) { - ASSERT(p_data); - ASSERT(p_data->p_buffer); - free( p_data->p_buffer ); - free( 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->small.l_index < SMALL_CACHE_SIZE ) + { + p_cache->small.p_stack[ p_cache->small.l_index ].l_size = + p_data->l_size; + p_cache->small.p_stack[ p_cache->small.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->large.l_index < LARGE_CACHE_SIZE ) + { + p_cache->large.p_stack[ p_cache->large.l_index ].l_size = + p_data->l_size; + p_cache->large.p_stack[ p_cache->large.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_garbage, pes_packet_t * p_pes ) +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; - free( p_data->p_buffer ); - free( p_data ); + DeletePacket( p_cache, p_data ); p_data = p_next; } - free( p_pes ); + 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 ); }