From: ddennedy Date: Mon, 26 Jan 2004 21:12:23 +0000 (+0000) Subject: westley updates for non-inline serialisation and code cleanup X-Git-Url: http://research.m1stereo.tv/gitweb?a=commitdiff_plain;h=73345685f05e06c7b2c6a9d2b5c6bcf1c642d82b;p=melted westley updates for non-inline serialisation and code cleanup git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@96 d19143bc-622f-0410-bfdd-b5b2a6649095 --- diff --git a/src/modules/westley/consumer_westley.c b/src/modules/westley/consumer_westley.c index ceba61b..d196ffb 100644 --- a/src/modules/westley/consumer_westley.c +++ b/src/modules/westley/consumer_westley.c @@ -72,6 +72,8 @@ struct serialise_context_s int tractor_count; int filter_count; int transition_count; + int pass; + mlt_properties producer_map; }; typedef struct serialise_context_s* serialise_context; @@ -101,7 +103,9 @@ static void serialise_service( serialise_context context, mlt_service service, x int i; xmlNode *child = node; char id[ 31 ]; + char key[ 11 ]; id[ 30 ] = '\0'; + key[ 10 ] = '\0'; // Iterate over consumer/producer connections while ( service != NULL ) @@ -112,16 +116,27 @@ static void serialise_service( serialise_context context, mlt_service service, x // Tell about the producer if ( strcmp( mlt_type, "producer" ) == 0 ) { - child = xmlNewChild( node, NULL, "producer", NULL ); + if ( context->pass == 0 ) + { + child = xmlNewChild( node, NULL, "producer", NULL ); + + // Set the id + if ( mlt_properties_get( properties, "id" ) == NULL ) + { + snprintf( id, 30, "producer%d", context->producer_count++ ); + xmlNewProp( child, "id", id ); + } + serialise_properties( properties, child ); - // Set the id - if ( mlt_properties_get( properties, "id" ) == NULL ) + // Add producer to the map + snprintf( key, 10, "%p", service ); + mlt_properties_set( context->producer_map, key, id ); + } + else { - snprintf( id, 30, "producer%d", context->producer_count++ ); - xmlNewProp( child, "id", id ); + snprintf( key, 10, "%p", service ); + xmlNewProp( node, "producer", mlt_properties_get( context->producer_map, key ) ); } - - serialise_properties( properties, child ); } // Tell about the framework container producers @@ -130,20 +145,38 @@ static void serialise_service( serialise_context context, mlt_service service, x // Recurse on multitrack's tracks if ( strcmp( mlt_properties_get( properties, "resource" ), "" ) == 0 ) { - child = xmlNewChild( node, NULL, "multitrack", NULL ); - - // Set the id - if ( mlt_properties_get( properties, "id" ) == NULL ) + if ( context->pass == 0 ) { - snprintf( id, 30, "multitrack%d", context->multitrack_count++ ); - xmlNewProp( child, "id", id ); + // Iterate over the tracks + for ( i = 0; i < mlt_multitrack_count( MLT_MULTITRACK( service ) ); i++ ) + { + serialise_service( context, MLT_SERVICE( mlt_multitrack_track( MLT_MULTITRACK( service ), i ) ), node ); + } } - - // Iterate over the tracks - for ( i = 0; i < mlt_multitrack_count( MLT_MULTITRACK( service ) ); i++ ) + else { - xmlNode *track = xmlNewChild( child, NULL, "track", NULL ); - serialise_service( context, MLT_SERVICE( mlt_multitrack_track( MLT_MULTITRACK( service ), i ) ), track ); + // Iterate over the tracks to collect the producers + for ( i = 0; i < mlt_multitrack_count( MLT_MULTITRACK( service ) ); i++ ) + { + serialise_service( context, MLT_SERVICE( mlt_multitrack_track( MLT_MULTITRACK( service ), i ) ), node ); + } + + child = xmlNewChild( node, NULL, "multitrack", NULL ); + + // Set the id + if ( mlt_properties_get( properties, "id" ) == NULL ) + { + snprintf( id, 30, "multitrack%d", context->multitrack_count++ ); + xmlNewProp( child, "id", id ); + } + + // Iterate over the tracks + for ( i = 0; i < mlt_multitrack_count( MLT_MULTITRACK( service ) ); i++ ) + { + xmlNode *track = xmlNewChild( child, NULL, "track", NULL ); + snprintf( key, 10, "%p", MLT_SERVICE( mlt_multitrack_track( MLT_MULTITRACK( service ), i ) ) ); + xmlNewProp( track, "producer", mlt_properties_get( context->producer_map, key ) ); + } } break; } @@ -152,55 +185,88 @@ static void serialise_service( serialise_context context, mlt_service service, x else if ( strcmp( mlt_properties_get( properties, "resource" ), "" ) == 0 ) { mlt_playlist_clip_info info; - child = xmlNewChild( node, NULL, "playlist", NULL ); - - // Set the id - if ( mlt_properties_get( properties, "id" ) == NULL ) - { - snprintf( id, 30, "playlist%d", context->playlist_count++ ); - xmlNewProp( child, "id", id ); - } - xmlNewProp( child, "in", mlt_properties_get( properties, "in" ) ); - xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) ); - - // Iterate over the playlist entries - for ( i = 0; i < mlt_playlist_count( MLT_PLAYLIST( service ) ); i++ ) + if ( context->pass == 0 ) { - if ( ! mlt_playlist_get_clip_info( MLT_PLAYLIST( service ), &info, i ) ) + // Iterate over the playlist entries to collect the producers + for ( i = 0; i < mlt_playlist_count( MLT_PLAYLIST( service ) ); i++ ) { - if ( strcmp( mlt_properties_get( mlt_producer_properties( info.producer ), "mlt_service" ), "blank" ) == 0 ) + if ( ! mlt_playlist_get_clip_info( MLT_PLAYLIST( service ), &info, i ) ) { - char length[ 20 ]; - length[ 19 ] = '\0'; - xmlNode *entry = xmlNewChild( child, NULL, "blank", NULL ); - snprintf( length, 19, "%lld", info.frame_count ); - xmlNewProp( entry, "length", length ); + if ( strcmp( mlt_properties_get( mlt_producer_properties( info.producer ), "mlt_service" ), "blank" ) != 0 ) + { + serialise_service( context, MLT_SERVICE( info.producer ), node ); + } } - else + } + + child = xmlNewChild( node, NULL, "playlist", NULL ); + + // Set the id + if ( mlt_properties_get( properties, "id" ) == NULL ) + { + snprintf( id, 30, "playlist%d", context->playlist_count++ ); + xmlNewProp( child, "id", id ); + } + + xmlNewProp( child, "in", mlt_properties_get( properties, "in" ) ); + xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) ); + + // Add producer to the map + snprintf( key, 10, "%p", service ); + mlt_properties_set( context->producer_map, key, id ); + + // Iterate over the playlist entries + for ( i = 0; i < mlt_playlist_count( MLT_PLAYLIST( service ) ); i++ ) + { + if ( ! mlt_playlist_get_clip_info( MLT_PLAYLIST( service ), &info, i ) ) { - xmlNode *entry = xmlNewChild( child, NULL, "entry", NULL ); - serialise_service( context, MLT_SERVICE( info.producer ), entry ); + if ( strcmp( mlt_properties_get( mlt_producer_properties( info.producer ), "mlt_service" ), "blank" ) == 0 ) + { + char length[ 20 ]; + length[ 19 ] = '\0'; + xmlNode *entry = xmlNewChild( child, NULL, "blank", NULL ); + snprintf( length, 19, "%lld", info.frame_count ); + xmlNewProp( entry, "length", length ); + } + else + { + 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 ) ); + } } } } + else + { + snprintf( key, 10, "%p", service ); + xmlNewProp( node, "producer", mlt_properties_get( context->producer_map, key ) ); + } } // Recurse on tractor's producer else if ( strcmp( mlt_properties_get( properties, "resource" ), "" ) == 0 ) { - child = xmlNewChild( node, NULL, "tractor", NULL ); - - // Set the id - if ( mlt_properties_get( properties, "id" ) == NULL ) + if ( context->pass == 0 ) { - snprintf( id, 30, "tractor%d", context->tractor_count++ ); - xmlNewProp( child, "id", id ); + // Recurse on connected producer + serialise_service( context, mlt_service_get_producer( service ), node ); } + else + { + child = xmlNewChild( node, NULL, "tractor", NULL ); - // Recurse on connected producer - serialise_service( context, mlt_service_get_producer( service ), child ); - + // Set the id + if ( mlt_properties_get( properties, "id" ) == NULL ) + { + snprintf( id, 30, "tractor%d", context->tractor_count++ ); + xmlNewProp( child, "id", id ); + } + + // Recurse on connected producer + serialise_service( context, mlt_service_get_producer( service ), child ); + } break; } } @@ -211,17 +277,19 @@ static void serialise_service( serialise_context context, mlt_service service, x // Recurse on connected producer serialise_service( context, MLT_SERVICE( MLT_FILTER( service )->producer ), node ); - child = xmlNewChild( node, NULL, "filter", NULL ); - - // Set the id - if ( mlt_properties_get( properties, "id" ) == NULL ) + if ( context->pass == 1 ) { - snprintf( id, 30, "filter%d", context->filter_count++ ); - xmlNewProp( child, "id", id ); - } + child = xmlNewChild( node, NULL, "filter", NULL ); - serialise_properties( properties, child ); + // Set the id + if ( mlt_properties_get( properties, "id" ) == NULL ) + { + snprintf( id, 30, "filter%d", context->filter_count++ ); + xmlNewProp( child, "id", id ); + } + serialise_properties( properties, child ); + } break; } @@ -231,17 +299,19 @@ static void serialise_service( serialise_context context, mlt_service service, x // Recurse on connected producer serialise_service( context, MLT_SERVICE( MLT_TRANSITION( service )->producer ), node ); - child = xmlNewChild( node, NULL, "transition", NULL ); - - // Set the id - if ( mlt_properties_get( properties, "id" ) == NULL ) + if ( context->pass == 1 ) { - snprintf( id, 30, "transition%d", context->transition_count++ ); - xmlNewProp( child, "id", id ); - } - - serialise_properties( properties, child ); + child = xmlNewChild( node, NULL, "transition", NULL ); + // Set the id + if ( mlt_properties_get( properties, "id" ) == NULL ) + { + snprintf( id, 30, "transition%d", context->transition_count++ ); + xmlNewProp( child, "id", id ); + } + + serialise_properties( properties, child ); + } break; } @@ -261,8 +331,8 @@ static int consumer_start( mlt_consumer this ) mlt_service service = mlt_service_get_producer( mlt_consumer_service( this ) ); if ( service != NULL ) { - struct serialise_context_s context; - memset( &context, 0, sizeof( struct serialise_context_s ) ); + struct serialise_context_s *context = calloc( 1, sizeof( struct serialise_context_s ) ); + context->producer_map = mlt_properties_new(); // Remember inigo if ( mlt_properties_get( mlt_service_properties( service ), "mlt_service" ) != NULL && @@ -271,9 +341,19 @@ static int consumer_start( mlt_consumer this ) // Ensure producer is a framework producer mlt_properties_set( mlt_service_properties( service ), "mlt_type", "mlt_producer" ); - - serialise_service( &context, service, root ); + // In pass one, we serialise the end producers and playlists, + // adding them to a map keyed by address. + serialise_service( context, service, root ); + + // In pass two, we serialise the tractor and reference the + // producers and playlists + context->pass++; + serialise_service( context, service, root ); + + mlt_properties_close( context->producer_map ); + free( context ); + if ( mlt_properties_get( mlt_consumer_properties( this ), "resource" ) == NULL ) xmlDocFormatDump( stderr, doc, 1 ); else diff --git a/src/modules/westley/producer_westley.c b/src/modules/westley/producer_westley.c index acc9215..ff5ba41 100644 --- a/src/modules/westley/producer_westley.c +++ b/src/modules/westley/producer_westley.c @@ -18,6 +18,8 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +// TODO: destroy unreferenced producers + #include "producer_westley.h" #include #include @@ -34,8 +36,7 @@ struct deserialise_context_s int stack_service_size; int track_count; mlt_properties producer_map; - int filter_count; - int transition_count; + mlt_properties destructors; }; typedef struct deserialise_context_s *deserialise_context; @@ -62,10 +63,21 @@ static mlt_service context_pop_service( deserialise_context this ) return result; } +// Set the destructor on a new service +static void track_service( mlt_properties properties, void *service, mlt_destructor destructor ) +{ + int registered = mlt_properties_get_int( properties, "registered" ); + char *key = mlt_properties_get( properties, "registered" ); + mlt_properties_set_data( properties, key, service, 0, destructor, NULL ); + mlt_properties_set_int( properties, "registered", ++ registered ); +} + static void on_start_tractor( deserialise_context context, const xmlChar *name, const xmlChar **atts) { mlt_service service = mlt_tractor_service( mlt_tractor_init() ); + track_service( context->destructors, service, (mlt_destructor) mlt_tractor_close ); + for ( ; atts != NULL && *atts != NULL; atts += 2 ) mlt_properties_set( mlt_service_properties( service ), (char*) atts[0], (char*) atts[1] ); @@ -76,6 +88,8 @@ static void on_start_multitrack( deserialise_context context, const xmlChar *nam { mlt_service service = mlt_multitrack_service( mlt_multitrack_init() ); + track_service( context->destructors, service, (mlt_destructor) mlt_multitrack_close ); + for ( ; atts != NULL && *atts != NULL; atts += 2 ) mlt_properties_set( mlt_service_properties( service ), (char*) atts[0], (char*) atts[1] ); @@ -87,6 +101,8 @@ static void on_start_playlist( deserialise_context context, const xmlChar *name, mlt_service service = mlt_playlist_service( mlt_playlist_init() ); mlt_properties properties = mlt_service_properties( service ); + track_service( context->destructors, service, (mlt_destructor) mlt_playlist_close ); + for ( ; atts != NULL && *atts != NULL; atts += 2 ) mlt_properties_set( properties, (char*) atts[0], (char*) atts[1] ); @@ -116,6 +132,9 @@ static void on_start_producer( deserialise_context context, const xmlChar *name, service = MLT_SERVICE( mlt_factory_producer( "inigo", args ) ); } + track_service( context->destructors, service, (mlt_destructor) mlt_producer_close ); + + // Add the producer to the producer map if ( mlt_properties_get( properties, "id" ) != NULL ) mlt_properties_set_data( context->producer_map, mlt_properties_get( properties, "id" ), service, 0, NULL, NULL ); @@ -167,6 +186,8 @@ static void on_start_filter( deserialise_context context, const xmlChar *name, c { char *id; mlt_properties properties = mlt_properties_new(); + char key[11]; + key[ 10 ] = '\0'; // Get the producer from the stack mlt_service producer = context_pop_service( context ); @@ -178,19 +199,12 @@ static void on_start_filter( deserialise_context context, const xmlChar *name, c // Create the filter mlt_service service = MLT_SERVICE( mlt_factory_filter( mlt_properties_get( properties, "mlt_service" ), NULL ) ); + track_service( context->destructors, service, (mlt_destructor) mlt_filter_close ); + // Connect the filter to the producer mlt_filter_connect( MLT_FILTER( service ), producer, mlt_properties_get_int( properties, "track" ) ); - // Generate an id if one does not exist - if ( mlt_properties_get( properties, "id" ) == NULL ) - { - char id[ 31 ]; - id[ 30 ] = '\0'; - snprintf( id, 30, "filter%d", context->filter_count++ ); - mlt_properties_set( properties, "id", id ); - } - // Propogate the properties mlt_properties_inherit( mlt_service_properties( service ), properties ); mlt_properties_close( properties ); @@ -209,28 +223,18 @@ static void on_start_filter( deserialise_context context, const xmlChar *name, c } // If a producer alias is in the producer_map, get it - id = mlt_properties_get( context->producer_map, mlt_properties_get( mlt_service_properties( producer ), "id" ) ); - if ( id != NULL && mlt_properties_get_data( context->producer_map, id, NULL ) != NULL ) - { + snprintf( key, 10, "%p", producer ); + if ( mlt_properties_get_data( context->producer_map, key, NULL ) != NULL ) + producer = mlt_properties_get_data( context->producer_map, key, NULL ); + + // Put the producer in the producer map + id = mlt_properties_get( mlt_service_properties( producer ), "id" ); + if ( id != NULL ) mlt_properties_set_data( context->producer_map, id, service, 0, NULL, NULL ); - - // For filter chain support, add an alias to the producer map - // alias the filter id as the producer id - mlt_properties_set( context->producer_map, mlt_properties_get( mlt_service_properties( service ), "id" ), id ); - } - else - { - // If the producer is in the producer_map, update it - id = mlt_properties_get( mlt_service_properties( producer ), "id" ); - if ( id != NULL && mlt_properties_get_data( context->producer_map, id, NULL ) != NULL ) - { - mlt_properties_set_data( context->producer_map, id, service, 0, NULL, NULL ); - - // For filter chain support, add an alias to the producer map - // alias the filter id as the producer id - mlt_properties_set( context->producer_map, mlt_properties_get( mlt_service_properties( service ), "id" ), id ); - } - } + + // For filter chain support, add an alias to the producer map + snprintf( key, 10, "%p", service ); + mlt_properties_set_data( context->producer_map, key, producer, 0, NULL, NULL ); // Push the filter onto the stack context_push_service( context, service ); @@ -250,14 +254,7 @@ static void on_start_transition( deserialise_context context, const xmlChar *nam // Create the transition mlt_service service = MLT_SERVICE( mlt_factory_transition( mlt_properties_get( properties, "mlt_service" ), NULL ) ); - // Generate an id if one does not exist - if ( mlt_properties_get( properties, "id" ) == NULL ) - { - char id[ 31 ]; - id[ 30 ] = '\0'; - snprintf( id, 30, "transition%d", context->transition_count++ ); - mlt_properties_set( properties, "id", id ); - } + track_service( context->destructors, service, (mlt_destructor) mlt_transition_close ); // Propogate the properties mlt_properties_inherit( mlt_service_properties( service ), properties ); @@ -393,6 +390,9 @@ mlt_producer producer_westley_init( char *filename ) struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) ); context->producer_map = mlt_properties_new(); + context->destructors = mlt_properties_new(); + // We need to track the number of registered filters + mlt_properties_set_int( context->destructors, "registered", 0 ); sax->startElement = on_start_element; sax->endElement = on_end_element; @@ -404,6 +404,8 @@ mlt_producer producer_westley_init( char *filename ) mlt_properties_close( context->producer_map ); mlt_service service = context_pop_service( context ); + // make the returned service destroy the connected services + mlt_properties_set_data( mlt_service_properties( service ), "__destructors__", context->destructors, 0, (mlt_destructor) mlt_properties_close, NULL ); free( context ); return MLT_PRODUCER( service );