]> git.sesse.net Git - mlt/commitdiff
pooling and properties checks; dv decoder stack; factory cleanup registering
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Fri, 26 Mar 2004 12:58:38 +0000 (12:58 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Fri, 26 Mar 2004 12:58:38 +0000 (12:58 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@247 d19143bc-622f-0410-bfdd-b5b2a6649095

src/framework/mlt_factory.c
src/framework/mlt_factory.h
src/framework/mlt_pool.c
src/framework/mlt_properties.c
src/modules/dv/producer_libdv.c
src/modules/fezzik.dict
src/modules/fezzik/producer_fezzik.c
src/modules/sdl/consumer_sdl.c

index dee338e3bab2d36d0716568c8db2791c48454de4..61093a13dfa657d8624880470768c0d81a306aaf 100644 (file)
@@ -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.
 */
 
index 7c943fbece92c70edabb8735b0bea43047a1ff5f..e2842ce277a02397f71724932de1283592e6f400 100644 (file)
@@ -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
index 72e11baf589db2e75610db2e451bc8fc6208c163..e908cbf76deda0de5816738c04748b8579cc367e 100644 (file)
@@ -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 );
 }
index 7a7010e7f07748bf8343d5e75f41032e48f00c9c..899bf9ad60516ca2fe9c822dd732d508659ccc77 100644 (file)
@@ -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
+       }
 }
 
index 30111dad2fc9e67a7612d1c7513623b64b36cddd..9ed89780d7eb0e53bfbdbd378111f15f5a68fa34 100644 (file)
@@ -20,6 +20,9 @@
 
 #include "producer_libdv.h"
 #include <framework/mlt_frame.h>
+#include <framework/mlt_deque.h>
+#include <framework/mlt_factory.h>
+#include <pthread.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
+/** 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 );
index 818c55db52693a2ba36eb435ce0e12f3d41f573b..0ba05b5d709a814c954318ded4344693d9126c31 100644 (file)
@@ -13,6 +13,7 @@ http://*=avformat
 *.mpg=mcmpeg,avformat
 *.mpeg=mcmpeg,avformat
 *.ogg=vorbis
+*.pgm=pixbuf
 *.png=pixbuf
 *.svg=pixbuf
 *.tga=pixbuf
index 2eafbc6582f1e38a8d4e276c77eed5b067a06c2a..b06e4203e0ff3a270c25d18389e01c2ed0aeb3a7 100644 (file)
@@ -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
index 1d1e95965b5631ade68f2661486ea40ab8264ffb..7d867df9369afb31b27e28240c8fd7201b6bf93a 100644 (file)
@@ -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 );