From 52c1bb26fcbb895824cd9237c228ea4834ce1433 Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Thu, 26 Aug 2004 14:16:56 +0000 Subject: [PATCH] Mlt Ref Counts and Playlist split/join git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@387 d19143bc-622f-0410-bfdd-b5b2a6649095 --- docs/framework.txt | 35 +++++---- setenv_mc | 3 +- src/framework/mlt_consumer.c | 22 +++--- src/framework/mlt_field.c | 7 +- src/framework/mlt_filter.c | 22 ++++-- src/framework/mlt_frame.c | 2 +- src/framework/mlt_multitrack.c | 15 ++-- src/framework/mlt_playlist.c | 95 +++++++++++++++++++++-- src/framework/mlt_playlist.h | 2 + src/framework/mlt_producer.c | 20 ++++- src/framework/mlt_producer.h | 3 +- src/framework/mlt_properties.c | 100 +++++++++++++++++++------ src/framework/mlt_properties.h | 5 ++ src/framework/mlt_service.c | 46 ++++++++++-- src/framework/mlt_service.h | 2 + src/framework/mlt_tractor.c | 21 ++---- src/framework/mlt_transition.c | 14 +++- src/modules/core/producer_colour.c | 2 +- src/modules/core/producer_noise.c | 2 +- src/modules/core/producer_ppm.c | 2 +- src/modules/dv/producer_libdv.c | 2 +- src/modules/fezzik/producer_hold.c | 2 +- src/modules/gtk2/producer_pango.c | 2 +- src/modules/gtk2/producer_pixbuf.c | 2 +- src/modules/westley/consumer_westley.c | 24 +++--- 25 files changed, 339 insertions(+), 113 deletions(-) diff --git a/docs/framework.txt b/docs/framework.txt index 07cc7128..4ffff1f5 100644 --- a/docs/framework.txt +++ b/docs/framework.txt @@ -23,8 +23,8 @@ Preamble: This document is split roughly into 3 sections. The first section provides a basic overview of MLT, the second section shows how it's used and the final - section shows shows structure and design, with an emphasis on how the system - is extended. + section shows structure and design, with an emphasis on how the system is + extended. Target Audience: @@ -303,11 +303,7 @@ Playlists: Instead of invoking mlt_factory_producer directly, we'll create a new function called create_playlist. This function is responsible for creating - the playlist, creating each producer, appending to the playlist and ensuring - that all the producers are cleaned up when the playlist is destroyed. The - last point is important - a close on the playlist won't explicitly close these - producers. In this example, we use unique "data" properties with destructors - to ensure closing. + the playlist, creating each producer and appending to the playlist. mlt_producer create_playlist( int argc, char **argv ) { @@ -321,26 +317,28 @@ Playlists: int i = 0; for ( i = 1; i < argc; i ++ ) { - // Define the unique key - char key[ 256 ]; - // Create the producer mlt_producer producer = mlt_factory_producer( NULL, argv[ i ] ); // Add it to the playlist mlt_playlist_append( playlist, producer ); - // Create a unique key for this producer - sprintf( key, "producer%d", i ); - - // Now we need to ensure the producers are destroyed - mlt_properties_set_data( properties, key, producer, 0, ( mlt_destructor )mlt_producer_close, NULL ); + // Close the producer (see below) + mlt_producer_close( producer ); } // Return the playlist as a producer return mlt_playlist_producer( playlist ); } + Notice that we close the producer after the append. Actually, what we're + doing is closing our reference to it - the playlist creates its own reference + to the producer on append and insert, and it will close its reference + when the playlist is destroyed[*]. + + Note also that if you append multiple instances of the same producer, it + will create multiple references to it. + Now all we need do is to replace these lines in the main function: // Create a normalised producer @@ -353,6 +351,10 @@ Playlists: and we have a means to play multiple clips. + [*] This reference functionality was introduced in mlt 0.1.2 - it is 100% + compatable with the early mechanism of registering the reference and + destructor with the properties of the playlist object. + Filters: @@ -579,6 +581,9 @@ Multiple Tracks and Transitions: and we have a means to play multiple clips with a horribly obtrusive watermark - just what the world needed, right? ;-) + Incidentally, the same thing could be achieved with the more trivial + watermark filter inserted between the producer and the consumer. + SECTION 3 - STRUCTURE AND DESIGN -------------------------------- diff --git a/setenv_mc b/setenv_mc index 5a26dde7..7b015e5b 100644 --- a/setenv_mc +++ b/setenv_mc @@ -3,5 +3,6 @@ export LD_LIBRARY_PATH=\ `pwd`/../mpeg_sdk_release/bin:\ -`pwd`/../dvcpro_sdk_release/lib +`pwd`/../dvcpro_sdk_release/lib:\ +`pwd`/../sr_sdk_release/lib diff --git a/src/framework/mlt_consumer.c b/src/framework/mlt_consumer.c index a07f72d1..f3632481 100644 --- a/src/framework/mlt_consumer.c +++ b/src/framework/mlt_consumer.c @@ -520,15 +520,19 @@ int mlt_consumer_is_stopped( mlt_consumer this ) void mlt_consumer_close( mlt_consumer this ) { - // Get the childs close function - void ( *consumer_close )( ) = this->close; + if ( this != NULL && mlt_properties_dec_ref( mlt_consumer_properties( this ) ) <= 0 ) + { + // Get the childs close function + void ( *consumer_close )( ) = this->close; - // Make sure it only gets called once - this->close = NULL; + // Make sure it only gets called once + this->close = NULL; + this->parent.close = NULL; - // Call the childs close if available - if ( consumer_close != NULL ) - consumer_close( this ); - else - mlt_service_close( &this->parent ); + // Call the childs close if available + if ( consumer_close != NULL ) + consumer_close( this ); + else + mlt_service_close( &this->parent ); + } } diff --git a/src/framework/mlt_field.c b/src/framework/mlt_field.c index 94c4cb8b..05a41e55 100644 --- a/src/framework/mlt_field.c +++ b/src/framework/mlt_field.c @@ -152,6 +152,11 @@ int mlt_field_plant_transition( mlt_field this, mlt_transition that, int a_track void mlt_field_close( mlt_field this ) { - free( this ); + if ( this != NULL && mlt_properties_dec_ref( mlt_field_properties( this ) ) <= 0 ) + { + //mlt_tractor_close( this->tractor ); + //mlt_multitrack_close( this->multitrack ); + free( this ); + } } diff --git a/src/framework/mlt_filter.c b/src/framework/mlt_filter.c index f140df52..37f91db3 100644 --- a/src/framework/mlt_filter.c +++ b/src/framework/mlt_filter.c @@ -44,6 +44,10 @@ int mlt_filter_init( mlt_filter this, void *child ) // Override the get_frame method service->get_frame = filter_get_frame; + // Define the destructor + service->close = ( mlt_destructor )mlt_filter_close; + service->close_object = this; + // Default in, out, track properties mlt_properties_set_position( properties, "in", 0 ); mlt_properties_set_position( properties, "out", 0 ); @@ -192,9 +196,17 @@ static int filter_get_frame( mlt_service service, mlt_frame_ptr frame, int index void mlt_filter_close( mlt_filter this ) { - if ( this->close != NULL ) - this->close( this ); - else - mlt_service_close( &this->parent ); - free( this ); + if ( this != NULL && mlt_properties_dec_ref( mlt_filter_properties( this ) ) <= 0 ) + { + if ( this->close != NULL ) + { + this->close( this ); + } + else + { + this->parent.close = NULL; + mlt_service_close( &this->parent ); + } + free( this ); + } } diff --git a/src/framework/mlt_frame.c b/src/framework/mlt_frame.c index 401c8647..f0092ed9 100644 --- a/src/framework/mlt_frame.c +++ b/src/framework/mlt_frame.c @@ -341,7 +341,7 @@ int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *for void mlt_frame_close( mlt_frame this ) { - if ( this != NULL ) + if ( this != NULL && mlt_properties_dec_ref( mlt_frame_properties( this ) ) <= 0 ) { mlt_deque_close( this->stack_image ); mlt_deque_close( this->stack_audio ); diff --git a/src/framework/mlt_multitrack.c b/src/framework/mlt_multitrack.c index 2c3d927b..d00525d6 100644 --- a/src/framework/mlt_multitrack.c +++ b/src/framework/mlt_multitrack.c @@ -407,12 +407,15 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int ind void mlt_multitrack_close( mlt_multitrack this ) { - // Close the producer - mlt_producer_close( &this->parent ); + if ( this != NULL && mlt_properties_dec_ref( mlt_multitrack_properties( this ) ) <= 0 ) + { + // Close the producer + mlt_producer_close( &this->parent ); - // Free the list - free( this->list ); + // Free the list + free( this->list ); - // Free the object - free( this ); + // Free the object + free( this ); + } } diff --git a/src/framework/mlt_playlist.c b/src/framework/mlt_playlist.c index 440c9245..04e61d49 100644 --- a/src/framework/mlt_playlist.c +++ b/src/framework/mlt_playlist.c @@ -73,6 +73,10 @@ mlt_playlist mlt_playlist_init( ) // Override the producer get_frame producer->get_frame = producer_get_frame; + // Define the destructor + producer->close = ( mlt_destructor )mlt_playlist_close; + producer->close_object = this; + // Initialise blank mlt_producer_init( &this->blank, NULL ); mlt_properties_set( mlt_producer_properties( &this->blank ), "mlt_service", "blank" ); @@ -187,6 +191,8 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer this->count ++; + mlt_properties_inc_ref( mlt_producer_properties( producer ) ); + return mlt_playlist_virtual_refresh( this ); } @@ -442,6 +448,9 @@ int mlt_playlist_count( mlt_playlist this ) int mlt_playlist_clear( mlt_playlist this ) { + int i; + for ( i = 0; i < this->count; i ++ ) + mlt_producer_close( this->list[ i ]->producer ); this->count = 0; mlt_properties_set_double( mlt_playlist_properties( this ), "first_fps", 0 ); return mlt_playlist_virtual_refresh( this ); @@ -515,6 +524,9 @@ int mlt_playlist_remove( mlt_playlist this, int where ) // Get the clip info of the clip to be removed mlt_playlist_get_clip_info( this, &where_info, where ); + // Close the producer associated to the clip info + mlt_producer_close( where_info.producer ); + // Reorganise the list for ( i = where + 1; i < this->count; i ++ ) this->list[ i - 1 ] = this->list[ i ]; @@ -620,6 +632,68 @@ int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_ return error; } +/** Split a clip on the playlist at the given position. +*/ + +int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position ) +{ + int error = clip < 0 || clip >= this->count; + if ( error == 0 ) + { + playlist_entry *entry = this->list[ clip ]; + if ( position > 0 && position < entry->frame_count ) + { + int in = entry->frame_in; + int out = entry->frame_out; + mlt_playlist_resize_clip( this, clip, in, in + position ); + mlt_playlist_insert( this, entry->producer, clip + 1, in + position + 1, out ); + } + else + { + error = 1; + } + } + return error; +} + +/** Join 1 or more consecutive clips. +*/ + +int mlt_playlist_join( mlt_playlist this, int clip, int count, int merge ) +{ + int error = clip < 0 || ( clip + 1 ) >= this->count; + if ( error == 0 ) + { + int i = clip; + mlt_playlist new_clip = mlt_playlist_init( ); + if ( clip + count >= this->count ) + count = this->count - clip; + for ( i = 0; i <= count; i ++ ) + { + playlist_entry *entry = this->list[ clip ]; + char *resource = mlt_properties_get( mlt_producer_properties( entry->producer ), "resource" ); + if ( merge && resource != NULL && !strcmp( resource, "" ) ) + { + mlt_playlist old_clip = ( mlt_playlist )entry->producer; + while( old_clip->count ) + { + entry = old_clip->list[ 0 ]; + mlt_playlist_append_io( new_clip, entry->producer, entry->frame_in, entry->frame_out ); + mlt_playlist_remove( old_clip, 0 ); + } + } + else + { + mlt_playlist_append_io( new_clip, entry->producer, entry->frame_in, entry->frame_out ); + } + mlt_playlist_remove( this, clip ); + } + mlt_playlist_insert( this, mlt_playlist_producer( new_clip ), clip, 0, -1 ); + mlt_playlist_close( new_clip ); + } + return error; +} + /** Get the current frame. */ @@ -662,11 +736,18 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i void mlt_playlist_close( mlt_playlist this ) { - int i = 0; - mlt_producer_close( &this->parent ); - mlt_producer_close( &this->blank ); - for ( i = 0; i < this->count; i ++ ) - free( this->list[ i ] ); - free( this->list ); - free( this ); + if ( this != NULL && mlt_properties_dec_ref( mlt_playlist_properties( this ) ) <= 0 ) + { + int i = 0; + this->parent.close = NULL; + mlt_producer_close( &this->parent ); + mlt_producer_close( &this->blank ); + for ( i = 0; i < this->count; i ++ ) + { + mlt_producer_close( this->list[ i ]->producer ); + free( this->list[ i ] ); + } + free( this->list ); + free( this ); + } } diff --git a/src/framework/mlt_playlist.h b/src/framework/mlt_playlist.h index 913b6089..bfa61c03 100644 --- a/src/framework/mlt_playlist.h +++ b/src/framework/mlt_playlist.h @@ -61,6 +61,8 @@ extern int mlt_playlist_insert( mlt_playlist self, mlt_producer producer, int wh extern int mlt_playlist_remove( mlt_playlist self, int where ); extern int mlt_playlist_move( mlt_playlist self, int from, int to ); extern int mlt_playlist_resize_clip( mlt_playlist self, int clip, mlt_position in, mlt_position out ); +extern int mlt_playlist_split( mlt_playlist self, int clip, mlt_position position ); +extern int mlt_playlist_join( mlt_playlist self, int clip, int count, int merge ); extern void mlt_playlist_close( mlt_playlist self ); #endif diff --git a/src/framework/mlt_producer.c b/src/framework/mlt_producer.c index fc161f5d..8ff5dc1f 100644 --- a/src/framework/mlt_producer.c +++ b/src/framework/mlt_producer.c @@ -58,6 +58,13 @@ int mlt_producer_init( mlt_producer this, void *child ) // The parent is the service mlt_service parent = &this->parent; + // Define the parent close + parent->close = ( mlt_destructor )mlt_producer_close; + parent->close_object = this; + + // For convenience, we'll assume the close_object is this + this->close_object = this; + // Get the properties of the parent mlt_properties properties = mlt_service_properties( parent ); @@ -309,8 +316,13 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind void mlt_producer_close( mlt_producer this ) { - if ( this->close != NULL ) - this->close( this ); - else - mlt_service_close( &this->parent ); + if ( this != NULL && mlt_properties_dec_ref( mlt_producer_properties( this ) ) <= 0 ) + { + this->parent.close = NULL; + + if ( this->close != NULL ) + this->close( this->close_object ); + else + mlt_service_close( &this->parent ); + } } diff --git a/src/framework/mlt_producer.h b/src/framework/mlt_producer.h index e94174c6..9bbcda80 100644 --- a/src/framework/mlt_producer.h +++ b/src/framework/mlt_producer.h @@ -33,7 +33,8 @@ struct mlt_producer_s // Public virtual methods int ( *get_frame )( mlt_producer, mlt_frame_ptr, int ); - void ( *close )( mlt_producer ); + mlt_destructor close; + void *close_object; // Private data void *local; diff --git a/src/framework/mlt_properties.c b/src/framework/mlt_properties.c index 895be28a..189f8aff 100644 --- a/src/framework/mlt_properties.c +++ b/src/framework/mlt_properties.c @@ -40,12 +40,15 @@ typedef struct int count; int size; mlt_properties mirror; + int ref_count; } property_list; /** Memory leak checks. */ +//#define _MLT_PROPERTY_CHECKS_ + #ifdef _MLT_PROPERTY_CHECKS_ static int properties_created = 0; static int properties_destroyed = 0; @@ -71,6 +74,9 @@ int mlt_properties_init( mlt_properties this, void *child ) // Allocate the local structure this->local = calloc( sizeof( property_list ), 1 ); + + // Increment the ref count + ( ( property_list * )this->local )->ref_count = 1; } // Check that initialisation was successful @@ -156,6 +162,32 @@ static inline void mlt_properties_do_mirror( mlt_properties this, char *name ) } } +/** Maintain ref count to allow multiple uses of an mlt object. +*/ + +int mlt_properties_inc_ref( mlt_properties this ) +{ + if ( this != NULL ) + { + property_list *list = this->local; + return ++ list->ref_count; + } + return 0; +} + +/** Maintain ref count to allow multiple uses of an mlt object. +*/ + +int mlt_properties_dec_ref( mlt_properties this ) +{ + if ( this != NULL ) + { + property_list *list = this->local; + return -- list->ref_count; + } + return 0; +} + /** Allow the specification of a mirror. */ @@ -595,39 +627,65 @@ void mlt_properties_dump( mlt_properties this, FILE *output ) fprintf( output, "%s=%s\n", list->name[ i ], mlt_properties_get( this, list->name[ i ] ) ); } +void mlt_properties_debug( mlt_properties this, char *title, FILE *output ) +{ + fprintf( stderr, "%s: ", title ); + if ( this != NULL ) + { + property_list *list = this->local; + int i = 0; + fprintf( output, "[ ref=%d", list->ref_count ); + for ( i = 0; i < list->count; i ++ ) + if ( mlt_properties_get( this, list->name[ i ] ) != NULL ) + fprintf( output, ", %s=%s", list->name[ i ], mlt_properties_get( this, list->name[ i ] ) ); + fprintf( output, " ]" ); + } + fprintf( stderr, "\n" ); +} + /** Close the list. */ void mlt_properties_close( mlt_properties this ) { - if ( this != NULL ) + if ( this != NULL && mlt_properties_dec_ref( this ) <= 0 ) { - property_list *list = this->local; - int index = 0; - - // Clean up names and values - for ( index = list->count - 1; index >= 0; index -- ) + if ( this->close != NULL ) { - free( list->name[ index ] ); - mlt_property_close( list->value[ index ] ); + this->close( this->close_object ); } - - // 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 ); + else + { + property_list *list = this->local; + int index = 0; #ifdef _MLT_PROPERTY_CHECKS_ - // Increment destroyed count - properties_destroyed ++; + // Show debug info + mlt_properties_debug( this, "Closing", stderr ); - // Show current stats - these should match when the app is closed - fprintf( stderr, "Created %d, destroyed %d\n", properties_created, properties_destroyed ); + // 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 + + // Clean up names and values + for ( index = list->count - 1; index >= 0; index -- ) + { + free( list->name[ index ] ); + mlt_property_close( list->value[ index ] ); + } + + // 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 ); + } } } diff --git a/src/framework/mlt_properties.h b/src/framework/mlt_properties.h index c0be46e5..c57208e5 100644 --- a/src/framework/mlt_properties.h +++ b/src/framework/mlt_properties.h @@ -32,6 +32,8 @@ struct mlt_properties_s { void *child; void *local; + mlt_destructor close; + void *close_object; }; /** Public interface. @@ -40,6 +42,8 @@ struct mlt_properties_s extern int mlt_properties_init( mlt_properties, void *child ); extern mlt_properties mlt_properties_new( ); extern mlt_properties mlt_properties_load( char *file ); +extern int mlt_properties_inc_ref( mlt_properties self ); +extern int mlt_properties_dec_ref( mlt_properties self ); extern void mlt_properties_mirror( mlt_properties self, mlt_properties that ); extern int mlt_properties_inherit( mlt_properties self, mlt_properties that ); extern int mlt_properties_pass( mlt_properties self, mlt_properties that, char *prefix ); @@ -61,6 +65,7 @@ extern void *mlt_properties_get_data( mlt_properties self, char *name, int *leng extern int mlt_properties_rename( mlt_properties self, char *source, char *dest ); extern int mlt_properties_count( mlt_properties self ); extern void mlt_properties_dump( mlt_properties self, FILE *output ); +extern void mlt_properties_debug( mlt_properties self, char *title, FILE *output ); extern void mlt_properties_close( mlt_properties self ); #endif diff --git a/src/framework/mlt_service.c b/src/framework/mlt_service.c index 14ae45f5..7a66a577 100644 --- a/src/framework/mlt_service.c +++ b/src/framework/mlt_service.c @@ -59,6 +59,8 @@ static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int index ) int mlt_service_init( mlt_service this, void *child ) { + int error = 0; + // Initialise everything to NULL memset( this, 0, sizeof( struct mlt_service_s ) ); @@ -72,7 +74,14 @@ int mlt_service_init( mlt_service this, void *child ) this->get_frame = service_get_frame; // Initialise the properties - return mlt_properties_init( &this->parent, this ); + error = mlt_properties_init( &this->parent, this ); + if ( error == 0 ) + { + this->parent.close = ( mlt_destructor )mlt_service_close; + this->parent.close_object = this; + } + + return error; } /** Connect a producer service. @@ -110,6 +119,13 @@ int mlt_service_connect_producer( mlt_service this, mlt_service producer, int in // If we have space, assign the input if ( base->in != NULL && index >= 0 && index < base->size ) { + // Get the current service + mlt_service current = base->in[ index ]; + + // Increment the reference count on this producer + if ( producer != NULL ) + mlt_properties_inc_ref( mlt_service_properties( producer ) ); + // Now we disconnect the producer service from its consumer mlt_service_disconnect( producer ); @@ -123,6 +139,9 @@ int mlt_service_connect_producer( mlt_service this, mlt_service producer, int in // Now we connect the producer to its connected consumer mlt_service_connect( producer, this ); + // Close the current service + mlt_service_close( current ); + // Inform caller that all went well return 0; } @@ -142,7 +161,7 @@ static void mlt_service_disconnect( mlt_service this ) // Get the service base mlt_service_base *base = this->local; - // There's a bit more required here... + // Disconnect base->out = NULL; } } @@ -242,9 +261,24 @@ int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index ) void mlt_service_close( mlt_service this ) { - mlt_service_base *base = this->local; - free( base->in ); - free( base ); - mlt_properties_close( &this->parent ); + if ( this != NULL && mlt_properties_dec_ref( mlt_service_properties( this ) ) <= 0 ) + { + if ( this->close != NULL ) + { + this->close( this->close_object ); + } + else + { + mlt_service_base *base = this->local; + int i = 0; + for ( i = 0; i < base->count; i ++ ) + if ( base->in[ i ] != NULL ) + mlt_service_close( base->in[ i ] ); + free( base->in ); + free( base ); + this->parent.close = NULL; + mlt_properties_close( &this->parent ); + } + } } diff --git a/src/framework/mlt_service.h b/src/framework/mlt_service.h index 627bbbeb..a4a1ee0e 100644 --- a/src/framework/mlt_service.h +++ b/src/framework/mlt_service.h @@ -33,6 +33,8 @@ struct mlt_service_s // Protected virtual int ( *get_frame )( mlt_service self, mlt_frame_ptr frame, int index ); + mlt_destructor close; + void *close_object; // Private data void *local; diff --git a/src/framework/mlt_tractor.c b/src/framework/mlt_tractor.c index 91438680..5b571be9 100644 --- a/src/framework/mlt_tractor.c +++ b/src/framework/mlt_tractor.c @@ -41,7 +41,6 @@ struct mlt_tractor_s */ static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int track ); -static void producer_close( mlt_producer this ); /** Constructor for the tractor. */ @@ -59,7 +58,8 @@ mlt_tractor mlt_tractor_init( ) mlt_properties_set( mlt_producer_properties( producer ), "mlt_service", "tractor" ); producer->get_frame = producer_get_frame; - producer->close = producer_close; + producer->close = ( mlt_destructor )mlt_tractor_close; + producer->close_object = this; } else { @@ -252,16 +252,11 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra void mlt_tractor_close( mlt_tractor this ) { - this->parent.close = NULL; - mlt_producer_close( &this->parent ); - free( this ); -} - -/** Close the producer. -*/ - -static void producer_close( mlt_producer this ) -{ - mlt_tractor_close( this->child ); + if ( this != NULL && mlt_properties_dec_ref( mlt_tractor_properties( this ) ) <= 0 ) + { + this->parent.close = NULL; + mlt_producer_close( &this->parent ); + free( this ); + } } diff --git a/src/framework/mlt_transition.c b/src/framework/mlt_transition.c index afafc230..13957752 100644 --- a/src/framework/mlt_transition.c +++ b/src/framework/mlt_transition.c @@ -45,6 +45,8 @@ int mlt_transition_init( mlt_transition this, void *child ) mlt_properties properties = mlt_transition_properties( this ); service->get_frame = transition_get_frame; + service->close = ( mlt_destructor )mlt_transition_close; + service->close_object = this; mlt_properties_set_position( properties, "in", 0 ); mlt_properties_set_position( properties, "out", 0 ); @@ -230,8 +232,12 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i void mlt_transition_close( mlt_transition this ) { - if ( this->close != NULL ) - this->close( this ); - else - mlt_service_close( &this->parent ); + if ( this != NULL && mlt_properties_dec_ref( mlt_transition_properties( this ) ) <= 0 ) + { + this->parent.close = NULL; + if ( this->close != NULL ) + this->close( this ); + else + mlt_service_close( &this->parent ); + } } diff --git a/src/modules/core/producer_colour.c b/src/modules/core/producer_colour.c index ecd9a3ff..29bde448 100644 --- a/src/modules/core/producer_colour.c +++ b/src/modules/core/producer_colour.c @@ -45,7 +45,7 @@ mlt_producer producer_colour_init( char *colour ) // Callback registration producer->get_frame = producer_get_frame; - producer->close = producer_close; + producer->close = ( mlt_destructor )producer_close; // Set the default properties mlt_properties_set( properties, "resource", colour == NULL ? "0x000000ff" : colour ); diff --git a/src/modules/core/producer_noise.c b/src/modules/core/producer_noise.c index fe86075b..54d0474d 100644 --- a/src/modules/core/producer_noise.c +++ b/src/modules/core/producer_noise.c @@ -60,7 +60,7 @@ mlt_producer producer_noise_init( void *arg ) // Callback registration this->get_frame = producer_get_frame; - this->close = producer_close; + this->close = ( mlt_destructor )producer_close; } return this; diff --git a/src/modules/core/producer_ppm.c b/src/modules/core/producer_ppm.c index 4155783b..a0a9896f 100644 --- a/src/modules/core/producer_ppm.c +++ b/src/modules/core/producer_ppm.c @@ -48,7 +48,7 @@ mlt_producer producer_ppm_init( void *command ) mlt_properties properties = mlt_producer_properties( producer ); producer->get_frame = producer_get_frame; - producer->close = producer_close; + producer->close = ( mlt_destructor )producer_close; if ( command != NULL ) { diff --git a/src/modules/dv/producer_libdv.c b/src/modules/dv/producer_libdv.c index 3891681e..4abf75ae 100644 --- a/src/modules/dv/producer_libdv.c +++ b/src/modules/dv/producer_libdv.c @@ -139,7 +139,7 @@ mlt_producer producer_libdv_init( char *filename ) mlt_properties properties = mlt_producer_properties( producer ); // Register transport implementation with the producer - producer->close = producer_close; + producer->close = ( mlt_destructor )producer_close; // Register our get_frame implementation with the producer producer->get_frame = producer_get_frame; diff --git a/src/modules/fezzik/producer_hold.c b/src/modules/fezzik/producer_hold.c index 6c338779..08c0247d 100644 --- a/src/modules/fezzik/producer_hold.c +++ b/src/modules/fezzik/producer_hold.c @@ -62,7 +62,7 @@ mlt_producer producer_hold_init( char *arg ) // Override the get_frame method this->get_frame = producer_get_frame; - this->close = producer_close; + this->close = ( mlt_destructor )producer_close; } else { diff --git a/src/modules/gtk2/producer_pango.c b/src/modules/gtk2/producer_pango.c index 7c81c290..e4969aba 100644 --- a/src/modules/gtk2/producer_pango.c +++ b/src/modules/gtk2/producer_pango.c @@ -95,7 +95,7 @@ mlt_producer producer_pango_init( const char *filename ) mlt_producer producer = &this->parent; producer->get_frame = producer_get_frame; - producer->close = producer_close; + producer->close = ( mlt_destructor )producer_close; // This is required to initialise gdk-pixbuf g_type_init(); diff --git a/src/modules/gtk2/producer_pixbuf.c b/src/modules/gtk2/producer_pixbuf.c index 95cae13a..3fc0fb07 100644 --- a/src/modules/gtk2/producer_pixbuf.c +++ b/src/modules/gtk2/producer_pixbuf.c @@ -71,7 +71,7 @@ mlt_producer producer_pixbuf_init( char *filename ) // Callback registration producer->get_frame = producer_get_frame; - producer->close = producer_close; + producer->close = ( mlt_destructor )producer_close; // Set the default properties mlt_properties_set( properties, "resource", filename ); diff --git a/src/modules/westley/consumer_westley.c b/src/modules/westley/consumer_westley.c index 85f21c8f..9b4adeb6 100644 --- a/src/modules/westley/consumer_westley.c +++ b/src/modules/westley/consumer_westley.c @@ -205,8 +205,11 @@ static void serialise_playlist( serialise_context context, mlt_service service, if ( info.producer != NULL ) { char *service_s = mlt_properties_get( mlt_producer_properties( info.producer ), "mlt_service" ); + char *resource_s = mlt_properties_get( mlt_producer_properties( info.producer ), "resource" ); if ( service_s != NULL && strcmp( service_s, "blank" ) != 0 ) serialise_service( context, MLT_SERVICE( info.producer ), node ); + else if ( resource_s != NULL && !strcmp( resource_s, "" ) ) + serialise_playlist( context, MLT_SERVICE( info.producer ), node ); } } } @@ -243,11 +246,14 @@ static void serialise_playlist( serialise_context context, mlt_service service, } else { + char temp[ 20 ]; xmlNode *entry = xmlNewChild( child, NULL, "entry", NULL ); snprintf( key, 10, "%p", MLT_SERVICE( info.producer ) ); xmlNewProp( entry, "producer", mlt_properties_get( context->producer_map, key ) ); - xmlNewProp( entry, "in", mlt_properties_get( mlt_producer_properties( info.producer ), "in" ) ); - xmlNewProp( entry, "out", mlt_properties_get( mlt_producer_properties( info.producer ), "out" ) ); + sprintf( temp, "%d", info.frame_in ); + xmlNewProp( entry, "in", temp ); + sprintf( temp, "%d", info.frame_out ); + xmlNewProp( entry, "out", temp ); } } } @@ -270,7 +276,7 @@ static void serialise_tractor( serialise_context context, mlt_service service, x if ( context->pass == 0 ) { // Recurse on connected producer - serialise_service( context, mlt_service_get_producer( service ), node ); + serialise_service( context, mlt_service_producer( service ), node ); } else { @@ -287,7 +293,7 @@ static void serialise_tractor( serialise_context context, mlt_service service, x xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) ); // Recurse on connected producer - serialise_service( context, mlt_service_get_producer( service ), child ); + serialise_service( context, mlt_service_producer( service ), child ); } } @@ -404,7 +410,7 @@ static void serialise_service( serialise_context context, mlt_service service, x } // Get the next connected service - service = mlt_service_get_producer( service ); + service = mlt_service_producer( service ); } } @@ -443,18 +449,12 @@ xmlDocPtr westley_make_doc( mlt_service service ) static int consumer_start( mlt_consumer this ) { - mlt_service inigo = NULL; xmlDocPtr doc = NULL; // Get the producer service - mlt_service service = mlt_service_get_producer( mlt_consumer_service( this ) ); + mlt_service service = mlt_service_producer( mlt_consumer_service( this ) ); if ( service != NULL ) { - // Remember inigo - if ( mlt_properties_get( mlt_service_properties( service ), "mlt_service" ) != NULL && - strcmp( mlt_properties_get( mlt_service_properties( service ), "mlt_service" ), "inigo" ) == 0 ) - inigo = service; - doc = westley_make_doc( service ); if ( mlt_properties_get( mlt_consumer_properties( this ), "resource" ) == NULL ) -- 2.39.2