From: lilo_booter Date: Fri, 26 Mar 2004 12:58:38 +0000 (+0000) Subject: pooling and properties checks; dv decoder stack; factory cleanup registering X-Git-Url: http://research.m1stereo.tv/gitweb?a=commitdiff_plain;h=2c0cf75e5da5906e48c5a6398bd48d04501283b9;p=melted pooling and properties checks; dv decoder stack; factory cleanup registering git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@247 d19143bc-622f-0410-bfdd-b5b2a6649095 --- diff --git a/src/framework/mlt_factory.c b/src/framework/mlt_factory.c index dee338e..61093a1 100644 --- a/src/framework/mlt_factory.c +++ b/src/framework/mlt_factory.c @@ -174,6 +174,16 @@ mlt_consumer mlt_factory_consumer( char *service, void *input ) return obj; } +/** Register an object for clean up. +*/ + +void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor ) +{ + char unique[ 256 ]; + sprintf( unique, "%08d", mlt_properties_count( global_properties ) ); + mlt_properties_set_data( global_properties, unique, ptr, 0, destructor, NULL ); +} + /** Close the factory. */ diff --git a/src/framework/mlt_factory.h b/src/framework/mlt_factory.h index 7c943fb..e2842ce 100644 --- a/src/framework/mlt_factory.h +++ b/src/framework/mlt_factory.h @@ -30,6 +30,7 @@ extern mlt_producer mlt_factory_producer( char *name, void *input ); extern mlt_filter mlt_factory_filter( char *name, void *input ); extern mlt_transition mlt_factory_transition( char *name, void *input ); extern mlt_consumer mlt_factory_consumer( char *name, void *input ); +extern void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor ); extern void mlt_factory_close( ); #endif diff --git a/src/framework/mlt_pool.c b/src/framework/mlt_pool.c index 72e11ba..e908cbf 100644 --- a/src/framework/mlt_pool.c +++ b/src/framework/mlt_pool.c @@ -106,6 +106,9 @@ static void *pool_fetch( mlt_pool this ) // Initialise it if ( release != NULL ) { + // Increment the number of items allocated to this pool + this->count ++; + // Assign the pool release->pool = this; @@ -297,6 +300,17 @@ void mlt_pool_release( void *release ) void mlt_pool_close( ) { +#ifdef _MLT_POOL_CHECKS_ + // Stats dump on close + int i = 0; + for ( i = 0; i < mlt_properties_count( pools ); i ++ ) + { + mlt_pool pool = mlt_properties_get_data_at( pools, i, NULL ); + if ( pool->count ) + fprintf( stderr, "%d: allocated %d returned %d\n", pool->size, pool->count, mlt_deque_count( pool->stack ) ); + } +#endif + // Close the properties mlt_properties_close( pools ); } diff --git a/src/framework/mlt_properties.c b/src/framework/mlt_properties.c index 7a7010e..899bf9a 100644 --- a/src/framework/mlt_properties.c +++ b/src/framework/mlt_properties.c @@ -42,21 +42,38 @@ typedef struct } property_list; +/** Memory leak checks. +*/ + +#ifdef _MLT_PROPERTY_CHECKS_ +static int properties_created = 0; +static int properties_destroyed = 0; +#endif + /** Basic implementation. */ int mlt_properties_init( mlt_properties this, void *child ) { - // NULL all methods - memset( this, 0, sizeof( struct mlt_properties_s ) ); + if ( this != NULL ) + { +#ifdef _MLT_PROPERTY_CHECKS_ + // Increment number of properties created + properties_created ++; +#endif - // Assign the child of the object - this->child = child; + // NULL all methods + memset( this, 0, sizeof( struct mlt_properties_s ) ); - // Allocate the private structure - this->private = calloc( sizeof( property_list ), 1 ); + // Assign the child of the object + this->child = child; - return this->private == NULL; + // Allocate the private structure + this->private = calloc( sizeof( property_list ), 1 ); + } + + // Check that initialisation was successful + return this != NULL && this->private == NULL; } /** Constructor for stand alone object. @@ -520,7 +537,7 @@ void mlt_properties_dump( mlt_properties this, FILE *output ) property_list *list = this->private; int i = 0; for ( i = 0; i < list->count; i ++ ) - fprintf( stderr, "%s = %s\n", list->name[ i ], mlt_properties_get( this, list->name[ i ] ) ); + fprintf( stderr, "%s=%s\n", list->name[ i ], mlt_properties_get( this, list->name[ i ] ) ); } /** Close the list. @@ -528,23 +545,34 @@ void mlt_properties_dump( mlt_properties this, FILE *output ) void mlt_properties_close( mlt_properties this ) { - property_list *list = this->private; - int index = 0; - - // Clean up names and values - for ( index = list->count - 1; index >= 0; index -- ) + if ( this != NULL ) { - free( list->name[ index ] ); - mlt_property_close( list->value[ index ] ); - } + property_list *list = this->private; + int index = 0; - // Clear up the list - free( list->name ); - free( list->value ); - free( list ); + // Clean up names and values + for ( index = list->count - 1; index >= 0; index -- ) + { + free( list->name[ index ] ); + mlt_property_close( list->value[ index ] ); + } - // Free this now if this has no child - if ( this->child == NULL ) - free( this ); + // Clear up the list + free( list->name ); + free( list->value ); + free( list ); + + // Free this now if this has no child + if ( this->child == NULL ) + free( this ); + +#ifdef _MLT_PROPERTY_CHECKS_ + // Increment destroyed count + properties_destroyed ++; + + // Show current stats - these should match when the app is closed + fprintf( stderr, "Created %d, destroyed %d\n", properties_created, properties_destroyed ); +#endif + } } diff --git a/src/modules/dv/producer_libdv.c b/src/modules/dv/producer_libdv.c index 30111da..9ed8978 100644 --- a/src/modules/dv/producer_libdv.c +++ b/src/modules/dv/producer_libdv.c @@ -20,6 +20,9 @@ #include "producer_libdv.h" #include +#include +#include +#include #include #include #include @@ -29,13 +32,94 @@ #include #include +/** To conserve resources, we maintain a stack of dv decoders. +*/ + +static pthread_mutex_t decoder_lock = PTHREAD_MUTEX_INITIALIZER; +static mlt_properties dv_decoders = NULL; + +dv_decoder_t *dv_decoder_alloc( ) +{ + // We'll return a dv_decoder + dv_decoder_t *this = NULL; + + // Lock the mutex + pthread_mutex_lock( &decoder_lock ); + + // Create the properties if necessary + if ( dv_decoders == NULL ) + { + // Create the properties + dv_decoders = mlt_properties_new( ); + + // Create the stack + mlt_properties_set_data( dv_decoders, "stack", mlt_deque_init( ), 0, ( mlt_destructor )mlt_deque_close, NULL ); + + // Register the properties for clean up + mlt_factory_register_for_clean_up( dv_decoders, ( mlt_destructor )mlt_properties_close ); + } + + // Now try to obtain a decoder + if ( dv_decoders != NULL ) + { + // Obtain the stack + mlt_deque stack = mlt_properties_get_data( dv_decoders, "stack", NULL ); + + // Pop the top of the stack + this = mlt_deque_pop_back( stack ); + + // Create a new decoder if none available + if ( this == NULL ) + { + // We'll need a unique property ID for this + char label[ 256 ]; + + // Configure the decoder + this = dv_decoder_new( FALSE, FALSE, FALSE ); + this->quality = DV_QUALITY_COLOR | DV_QUALITY_AC_1; + this->audio->arg_audio_emphasis = 2; + dv_set_audio_correction( this, DV_AUDIO_CORRECT_AVERAGE ); + + // Register it with the properties to ensure clean up + // BUG: dv_decoder_free core dumps here + sprintf( label, "%p", this ); + //mlt_properties_set_data( dv_decoders, label, this, 0, ( mlt_destructor )dv_decoder_free, NULL ); + mlt_properties_set_data( dv_decoders, label, this, 0, NULL, NULL ); + } + } + + // Unlock the mutex + pthread_mutex_unlock( &decoder_lock ); + + return this; +} + +void dv_decoder_return( dv_decoder_t *this ) +{ + // Lock the mutex + pthread_mutex_lock( &decoder_lock ); + + // Now try to return the decoder + if ( dv_decoders != NULL ) + { + // Obtain the stack + mlt_deque stack = mlt_properties_get_data( dv_decoders, "stack", NULL ); + + // Push it back + mlt_deque_push_back( stack, this ); + } + + // Unlock the mutex + pthread_mutex_unlock( &decoder_lock ); +} + + typedef struct producer_libdv_s *producer_libdv; struct producer_libdv_s { struct mlt_producer_s parent; int fd; - dv_decoder_t *dv_decoder; int is_pal; uint64_t file_size; int frame_size; @@ -62,12 +146,6 @@ mlt_producer producer_libdv_init( char *filename ) // Register our get_frame implementation with the producer producer->get_frame = producer_get_frame; - // Create the dv_decoder - this->dv_decoder = dv_decoder_new( FALSE, FALSE, FALSE ); - this->dv_decoder->quality = DV_QUALITY_COLOR | DV_QUALITY_AC_1; - this->dv_decoder->audio->arg_audio_emphasis = 2; - dv_set_audio_correction( this->dv_decoder, DV_AUDIO_CORRECT_AVERAGE ); - // Open the file if specified this->fd = open( filename, O_RDONLY ); @@ -125,6 +203,9 @@ static int producer_collect_info( producer_libdv this ) // Get the properties mlt_properties properties = mlt_producer_properties( &this->parent ); + // Get a dv_decoder + dv_decoder_t *dv_decoder = dv_decoder_alloc( ); + // Determine the file size struct stat buf; fstat( this->fd, &buf ); @@ -152,9 +233,12 @@ static int producer_collect_info( producer_libdv this ) } // Parse the header for meta info - dv_parse_header( this->dv_decoder, dv_data ); + dv_parse_header( dv_decoder, dv_data ); mlt_properties_set_double( properties, "aspect_ratio", - dv_format_wide( this->dv_decoder ) ? ( this->is_pal ? 512.0/351.0 : 96.0/79.0 ) : ( this->is_pal ? 128.0/117.0 : 72.0/79.0 ) ); + dv_format_wide( dv_decoder ) ? ( this->is_pal ? 512.0/351.0 : 96.0/79.0 ) : ( this->is_pal ? 128.0/117.0 : 72.0/79.0 ) ); + + // Return the decoder + dv_decoder_return( dv_decoder ); } mlt_pool_release( dv_data ); @@ -171,12 +255,25 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma // Get the frames properties mlt_properties properties = mlt_frame_properties( this ); - // Get the dv decoder - dv_decoder_t *decoder = mlt_properties_get_data( properties, "dv_decoder", NULL ); + // Get a dv_decoder + dv_decoder_t *decoder = dv_decoder_alloc( ); // Get the dv data uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL ); + // Get and set the quality request + char *quality = mlt_frame_pop_service( this ); + + if ( quality != NULL ) + { + if ( strncmp( quality, "fast", 4 ) == 0 ) + decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_DC ); + else if ( strncmp( quality, "best", 4 ) == 0 ) + decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_AC_2 ); + else + decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_AC_1 ); + } + // Parse the header for meta info dv_parse_header( decoder, dv_data ); @@ -218,6 +315,9 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma *buffer = image; } + // Return the decoder + dv_decoder_return( decoder ); + return 0; } @@ -230,8 +330,8 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma // Get the frames properties mlt_properties properties = mlt_frame_properties( this ); - // Get the dv decoder - dv_decoder_t *decoder = mlt_properties_get_data( properties, "dv_decoder", NULL ); + // Get a dv_decoder + dv_decoder_t *decoder = dv_decoder_alloc( ); // Get the dv data uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL ); @@ -277,6 +377,9 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma mlt_frame_get_audio( this, buffer, format, frequency, channels, samples ); } + // Return the decoder + dv_decoder_return( decoder ); + return 0; } @@ -302,8 +405,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Get the frames properties mlt_properties properties = mlt_frame_properties( *frame ); - // Pass the dv decoder - mlt_properties_set_data( properties, "dv_decoder", this->dv_decoder, 0, NULL, NULL ); + // Get a dv_decoder + dv_decoder_t *dv_decoder = dv_decoder_alloc( ); // Pass the dv data mlt_properties_set_data( properties, "dv_data", data, frame_size_625_50, ( mlt_destructor )mlt_pool_release, NULL ); @@ -313,28 +416,23 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_properties_set_int( properties, "height", this->is_pal ? 576 : 480 ); mlt_properties_set_int( properties, "top_field_first", 0 ); - char *quality = mlt_properties_get( mlt_producer_properties( producer ), "quality" ); - if ( quality != NULL ) - { - if ( strncmp( quality, "fast", 4 ) == 0 ) - this->dv_decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_DC ); - else if ( strncmp( quality, "best", 4 ) == 0 ) - this->dv_decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_AC_2 ); - else - this->dv_decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_AC_1 ); - } - // Parse the header for meta info - dv_parse_header( this->dv_decoder, data ); - mlt_properties_set_int( properties, "progressive", dv_is_progressive( this->dv_decoder ) ); + dv_parse_header( dv_decoder, data ); + mlt_properties_set_int( properties, "progressive", dv_is_progressive( dv_decoder ) ); mlt_properties_set_double( properties, "aspect_ratio", - dv_format_wide( this->dv_decoder ) ? ( this->is_pal ? 512.0/351.0 : 96.0/79.0 ) : ( this->is_pal ? 128.0/117.0 : 72.0/79.0 ) ); + dv_format_wide( dv_decoder ) ? ( this->is_pal ? 512.0/351.0 : 96.0/79.0 ) : ( this->is_pal ? 128.0/117.0 : 72.0/79.0 ) ); // Hmm - register audio callback ( *frame )->get_audio = producer_get_audio; - + + // Push the quality string + mlt_frame_push_service( *frame, mlt_properties_get( mlt_producer_properties( producer ), "quality" ) ); + // Push the get_image method on to the stack mlt_frame_push_get_image( *frame, producer_get_image ); + + // Return the decoder + dv_decoder_return( dv_decoder ); } else { @@ -355,9 +453,6 @@ static void producer_close( mlt_producer parent ) // Obtain this producer_libdv this = parent->child; - // Free the dv deconder - //dv_decoder_free( this->dv_decoder ); - // Close the file if ( this->fd > 0 ) close( this->fd ); diff --git a/src/modules/fezzik.dict b/src/modules/fezzik.dict index 818c55d..0ba05b5 100644 --- a/src/modules/fezzik.dict +++ b/src/modules/fezzik.dict @@ -13,6 +13,7 @@ http://*=avformat *.mpg=mcmpeg,avformat *.mpeg=mcmpeg,avformat *.ogg=vorbis +*.pgm=pixbuf *.png=pixbuf *.svg=pixbuf *.tga=pixbuf diff --git a/src/modules/fezzik/producer_fezzik.c b/src/modules/fezzik/producer_fezzik.c index 2eafbc6..b06e420 100644 --- a/src/modules/fezzik/producer_fezzik.c +++ b/src/modules/fezzik/producer_fezzik.c @@ -88,6 +88,7 @@ static mlt_producer create_producer( char *file ) char temp[ 1024 ]; sprintf( temp, "%s/fezzik.dict", mlt_factory_prefix( ) ); dictionary = mlt_properties_load( temp ); + mlt_factory_register_for_clean_up( dictionary, ( mlt_destructor )mlt_properties_close ); } // Convert the lookup string to lower case diff --git a/src/modules/sdl/consumer_sdl.c b/src/modules/sdl/consumer_sdl.c index 1d1e959..7d867df 100644 --- a/src/modules/sdl/consumer_sdl.c +++ b/src/modules/sdl/consumer_sdl.c @@ -103,7 +103,7 @@ mlt_consumer consumer_sdl_init( char *arg ) mlt_properties_set( this->properties, "rescale", "nearest" ); // Default buffer for low latency - mlt_properties_set_int( this->properties, "buffer", 2 ); + mlt_properties_set_int( this->properties, "buffer", 1 ); // Default progressive true mlt_properties_set_int( this->properties, "progressive", 0 );