From 363d095af9149cc181e92a35d2e34e583d061747 Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Mon, 6 Sep 2004 12:14:09 +0000 Subject: [PATCH] Filter attachments to services git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@409 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/framework/mlt_producer.c | 89 +---------------------- src/framework/mlt_service.c | 123 +++++++++++++++++++++++++++++++- src/framework/mlt_service.h | 4 + src/inigo/inigo.c | 3 +- src/modules/core/filter_region.c | 6 ++ src/modules/core/filter_watermark.c | 27 ++++++- src/modules/core/transition_region.c | 22 ++++++ src/modules/dv/producer_libdv.c | 9 ++- src/modules/inigo/producer_inigo.c | 22 ++++++ src/modules/sdl/consumer_sdl.c | 5 ++ src/modules/westley/consumer_westley.c | 25 ++++--- 11 files changed, 228 insertions(+), 107 deletions(-) diff --git a/src/framework/mlt_producer.c b/src/framework/mlt_producer.c index 4fda305..acfaad1 100644 --- a/src/framework/mlt_producer.c +++ b/src/framework/mlt_producer.c @@ -314,18 +314,8 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind } else { - mlt_properties properties = mlt_producer_properties( this ); - mlt_filter *filters = mlt_properties_get_data( properties, "_filters", NULL ); - int count = mlt_properties_get_int( properties, "_filter_count" ); - int i; - // Get the frame from the implementation result = this->get_frame( this, frame, index ); - - // Process the frame with the attached filters - for ( i = 0; i < count; i ++ ) - if ( filters[ i ] != NULL ) - mlt_filter_process( filters[ i ], *frame ); } // Copy the fps and speed of the producer onto the frame @@ -344,41 +334,7 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind int mlt_producer_attach( mlt_producer this, mlt_filter filter ) { - int error = this == NULL || filter == NULL; - if ( error == 0 ) - { - int i = 0; - int size = 0; - mlt_properties properties = mlt_producer_properties( this ); - mlt_filter *filters = mlt_properties_get_data( properties, "_filters", &size ); - int count = mlt_properties_get_int( properties, "_filter_count" ); - - for ( i = 0; error == 0 && i < count; i ++ ) - if ( filters[ i ] == filter ) - error = 1; - - if ( error == 0 ) - { - if ( count == size ) - { - size += 10; - filters = realloc( filters, size * sizeof( mlt_filter ) ); - mlt_properties_set_data( properties, "_filters", filters, size, NULL, NULL ); - } - - if ( filters != NULL ) - { - mlt_properties_inc_ref( mlt_filter_properties( filter ) ); - filters[ count ++ ] = filter; - mlt_properties_set_int( properties, "_filter_count", count ); - } - else - { - error = 2; - } - } - } - return error; + return mlt_service_attach( mlt_producer_service( this ), filter ); } /** Detach a filter. @@ -386,30 +342,7 @@ int mlt_producer_attach( mlt_producer this, mlt_filter filter ) int mlt_producer_detach( mlt_producer this, mlt_filter filter ) { - int error = this == NULL || filter == NULL; - if ( error == 0 ) - { - int i = 0; - int size = 0; - mlt_properties properties = mlt_producer_properties( this ); - mlt_filter *filters = mlt_properties_get_data( properties, "_filters", &size ); - int count = mlt_properties_get_int( properties, "_filter_count" ); - - for ( i = 0; i < count; i ++ ) - if ( filters[ i ] == filter ) - break; - - if ( i < count ) - { - mlt_filter filter = filters[ i ]; - filters[ i ] = NULL; - for ( i ++ ; i < count; i ++ ) - filters[ i - 1 ] = filters[ i ]; - mlt_properties_set_int( properties, "_filter_count", -- count ); - mlt_filter_close( filter ); - } - } - return error; + return mlt_service_detach( mlt_producer_service( this ), filter ); } /** Retrieve a filter. @@ -417,16 +350,7 @@ int mlt_producer_detach( mlt_producer this, mlt_filter filter ) mlt_filter mlt_producer_filter( mlt_producer this, int index ) { - mlt_filter filter = NULL; - if ( this != NULL ) - { - mlt_properties properties = mlt_producer_properties( this ); - mlt_filter *filters = mlt_properties_get_data( properties, "_filters", NULL ); - int count = mlt_properties_get_int( properties, "_filter_count" ); - if ( index >= 0 && index < count ) - filter = filters[ index ]; - } - return filter; + return mlt_service_filter( mlt_producer_service( this ), index ); } /** Close the producer. @@ -436,13 +360,6 @@ void mlt_producer_close( mlt_producer this ) { if ( this != NULL && mlt_properties_dec_ref( mlt_producer_properties( this ) ) <= 0 ) { - mlt_properties properties = mlt_producer_properties( this ); - mlt_filter *filters = mlt_properties_get_data( properties, "_filters", NULL ); - int count = mlt_properties_get_int( properties, "_filter_count" ); - - while( count -- ) - mlt_producer_detach( this, filters[ 0 ] ); - this->parent.close = NULL; if ( this->close != NULL ) diff --git a/src/framework/mlt_service.c b/src/framework/mlt_service.c index 6df3630..0851b9a 100644 --- a/src/framework/mlt_service.c +++ b/src/framework/mlt_service.c @@ -20,6 +20,7 @@ #include "config.h" #include "mlt_service.h" +#include "mlt_filter.h" #include "mlt_frame.h" #include #include @@ -44,6 +45,9 @@ typedef struct int count; mlt_service *in; mlt_service out; + int filter_count; + int filter_size; + mlt_filter *filters; } mlt_service_base; @@ -255,17 +259,128 @@ mlt_properties mlt_service_properties( mlt_service self ) return self != NULL ? &self->parent : NULL; } +/** Recursively apply attached filters +*/ + +static void apply_filters( mlt_service this, mlt_frame frame, int index ) +{ + mlt_properties properties = mlt_service_properties( this ); + mlt_service_base *base = this->local; + int i; + + if ( mlt_properties_get_int( properties, "_filter_private" ) == 0 ) + { + // Process the frame with the attached filters + for ( i = 0; i < base->filter_count; i ++ ) + { + if ( base->filters[ i ] != NULL ) + { + mlt_filter_process( base->filters[ i ], frame ); + apply_filters( mlt_filter_service( base->filters[ i ] ), frame, index ); + } + } + } +} + /** Obtain a frame. */ int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index ) { if ( this != NULL ) - return this->get_frame( this, frame, index ); + { + int result = this->get_frame( this, frame, index ); + if ( result == 0 ) + apply_filters( this, *frame, index ); + return result; + } *frame = mlt_frame_init( ); return 0; } +/** Attach a filter. +*/ + +int mlt_service_attach( mlt_service this, mlt_filter filter ) +{ + int error = this == NULL || filter == NULL; + if ( error == 0 ) + { + int i = 0; + mlt_properties properties = mlt_service_properties( this ); + mlt_service_base *base = this->local; + + for ( i = 0; error == 0 && i < base->filter_count; i ++ ) + if ( base->filters[ i ] == filter ) + error = 1; + + if ( error == 0 ) + { + if ( base->filter_count == base->filter_size ) + { + base->filter_size += 10; + base->filters = realloc( base->filters, base->filter_size * sizeof( mlt_filter ) ); + } + + if ( base->filters != NULL ) + { + mlt_properties_inc_ref( mlt_filter_properties( filter ) ); + base->filters[ base->filter_count ++ ] = filter; + mlt_events_fire( properties, "service-changed", NULL ); + } + else + { + error = 2; + } + } + } + return error; +} + +/** Detach a filter. +*/ + +int mlt_service_detach( mlt_service this, mlt_filter filter ) +{ + int error = this == NULL || filter == NULL; + if ( error == 0 ) + { + int i = 0; + mlt_service_base *base = this->local; + mlt_properties properties = mlt_service_properties( this ); + + for ( i = 0; i < base->filter_count; i ++ ) + if ( base->filters[ i ] == filter ) + break; + + if ( i < base->filter_count ) + { + base->filters[ i ] = NULL; + for ( i ++ ; i < base->filter_count; i ++ ) + base->filters[ i - 1 ] = base->filters[ i ]; + base->filter_count --; + mlt_filter_close( filter ); + mlt_events_fire( properties, "service-changed", NULL ); + } + } + return error; +} + +/** Retrieve a filter. +*/ + +mlt_filter mlt_service_filter( mlt_service this, int index ) +{ + mlt_filter filter = NULL; + if ( this != NULL ) + { + mlt_service_base *base = this->local; + if ( index >= 0 && index < base->filter_count ) + filter = base->filters[ index ]; + } + return filter; +} + /** Close the service. */ @@ -281,12 +396,16 @@ void mlt_service_close( mlt_service this ) { mlt_service_base *base = this->local; int i = 0; + int count = base->filter_count; + while( count -- ) + mlt_service_detach( this, base->filters[ 0 ] ); + free( base->filters ); for ( i = 0; i < base->count; i ++ ) if ( base->in[ i ] != NULL ) mlt_service_close( base->in[ i ] ); + this->parent.close = NULL; 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 a4a1ee0..47cd929 100644 --- a/src/framework/mlt_service.h +++ b/src/framework/mlt_service.h @@ -50,6 +50,10 @@ extern int mlt_service_get_frame( mlt_service self, mlt_frame_ptr frame, int ind extern mlt_properties mlt_service_properties( mlt_service self ); extern mlt_service mlt_service_consumer( mlt_service self ); extern mlt_service mlt_service_producer( mlt_service self ); +extern int mlt_service_attach( mlt_service self, mlt_filter filter ); +extern int mlt_service_detach( mlt_service self, mlt_filter filter ); +extern mlt_filter mlt_service_filter( mlt_service self, int index ); + extern void mlt_service_close( mlt_service self ); // I'm not sure about self one - leaving it out of docs for now (only used in consumer_westley) diff --git a/src/inigo/inigo.c b/src/inigo/inigo.c index 41a0341..91b283a 100644 --- a/src/inigo/inigo.c +++ b/src/inigo/inigo.c @@ -271,7 +271,8 @@ int main( int argc, char **argv ) { fprintf( stderr, "Usage: inigo [ -group [ name=value ]* ]\n" " [ -consumer id[:arg] [ name=value ]* ]\n" - " [ -filter id[:arg] [ name=value ] * ]\n" + " [ -filter filter[:arg] [ name=value ] * ]\n" + " [ -attach filter[:arg] [ name=value ] * ]\n" " [ -transition id[:arg] [ name=value ] * ]\n" " [ -blank frames ]\n" " [ -track ]\n" diff --git a/src/modules/core/filter_region.c b/src/modules/core/filter_region.c index 635b390..db69b66 100644 --- a/src/modules/core/filter_region.c +++ b/src/modules/core/filter_region.c @@ -46,6 +46,9 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) // Register with the filter mlt_properties_set_data( properties, "_transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL ); + + // Pass a reference to this filter down + mlt_properties_set_data( mlt_transition_properties( transition ), "_region_filter", this, 0, NULL, NULL ); } // Pass all properties down @@ -74,6 +77,9 @@ mlt_filter filter_region_init( void *arg ) // Resource defines the shape of the region mlt_properties_set( properties, "resource", arg == NULL ? "rectangle" : arg ); + + // Ensure that attached filters are handled privately + mlt_properties_set_int( properties, "_filter_private", 1 ); } // Return the filter diff --git a/src/modules/core/filter_watermark.c b/src/modules/core/filter_watermark.c index afe036e..883db69 100644 --- a/src/modules/core/filter_watermark.c +++ b/src/modules/core/filter_watermark.c @@ -131,10 +131,29 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format // Get the b frame and process with composite if successful if ( mlt_service_get_frame( service, &b_frame, 0 ) == 0 ) - mlt_transition_process( composite, frame, b_frame ); - - // Get the image - error = mlt_frame_get_image( frame, image, format, width, height, 1 ); + { + if ( mlt_properties_get_int( properties, "reverse" ) == 0 ) + { + mlt_transition_process( composite, frame, b_frame ); + + // Get the image + error = mlt_frame_get_image( frame, image, format, width, height, 1 ); + } + else + { + mlt_properties a_props = mlt_frame_properties( frame ); + mlt_properties b_props = mlt_frame_properties( b_frame ); + mlt_transition_process( composite, b_frame, frame ); + mlt_properties_set( a_props, "rescale.interp", "nearest" ); + mlt_properties_set( b_props, "rescale.interp", "nearest" ); + mlt_properties_set_int( b_props, "consumer_aspect_ratio", 1 ); + error = mlt_frame_get_image( b_frame, image, format, width, height, 1 ); + mlt_properties_set_data( b_props, "image", *image, 0, NULL, NULL ); + mlt_properties_set_data( a_props, "image", *image, *width * *height * 2, mlt_pool_release, NULL ); + mlt_properties_set_int( a_props, "width", *width ); + mlt_properties_set_int( a_props, "height", *height ); + } + } // Close the b frame mlt_frame_close( b_frame ); diff --git a/src/modules/core/transition_region.c b/src/modules/core/transition_region.c index e8391c5..aa7b660 100644 --- a/src/modules/core/transition_region.c +++ b/src/modules/core/transition_region.c @@ -129,6 +129,23 @@ static uint8_t *filter_get_alpha_mask( mlt_frame this ) return alpha; } +static void apply_filters( mlt_filter this, mlt_frame frame, int index ) +{ + mlt_service service = mlt_filter_service( this ); + mlt_properties properties = mlt_filter_properties( this ); + int i; + + if ( index == 0 || mlt_properties_get_int( properties, "_filter_private" ) == 0 ) + { + mlt_filter filter = NULL; + for ( i = 0; ( filter = mlt_service_filter( service, i ) ) != NULL; i ++ ) + { + mlt_filter_process( filter, frame ); + apply_filters( filter, frame, 1 ); + } + } +} + /** Do it :-). */ @@ -297,6 +314,11 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for filter = mlt_properties_get_data( properties, id, NULL ); } + // Allow filters to be attached to a region filter + filter = mlt_properties_get_data( properties, "_region_filter", NULL ); + if ( filter != NULL ) + apply_filters( filter, b_frame, 0 ); + // Hmm - this is probably going to go wrong.... mlt_frame_set_position( frame, position ); diff --git a/src/modules/dv/producer_libdv.c b/src/modules/dv/producer_libdv.c index 4abf75a..7a0c16b 100644 --- a/src/modules/dv/producer_libdv.c +++ b/src/modules/dv/producer_libdv.c @@ -221,9 +221,12 @@ static int producer_collect_info( producer_libdv this ) double fps = this->is_pal ? 25 : 30000.0 / 1001.0; if ( mlt_properties_get_double( properties, "fps" ) == fps ) { - mlt_properties_set_position( properties, "length", this->frames_in_file ); - mlt_properties_set_position( properties, "in", 0 ); - mlt_properties_set_position( properties, "out", this->frames_in_file - 1 ); + if ( this->frames_in_file > 0 ) + { + mlt_properties_set_position( properties, "length", this->frames_in_file ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", this->frames_in_file - 1 ); + } } else { diff --git a/src/modules/inigo/producer_inigo.c b/src/modules/inigo/producer_inigo.c index 9dc560e..83434cf 100644 --- a/src/modules/inigo/producer_inigo.c +++ b/src/modules/inigo/producer_inigo.c @@ -77,6 +77,17 @@ static mlt_producer create_producer( mlt_field field, char *file ) return result; } +static mlt_filter create_attach( mlt_field field, char *id, int track ) +{ + char *arg = strchr( id, ':' ); + if ( arg != NULL ) + *arg ++ = '\0'; + mlt_filter filter = mlt_factory_filter( id, arg ); + if ( filter != NULL ) + track_service( field, filter, ( mlt_destructor )mlt_filter_close ); + return filter; +} + static mlt_filter create_filter( mlt_field field, char *id, int track ) { char *arg = strchr( id, ':' ); @@ -134,6 +145,17 @@ mlt_producer producer_inigo_init( char **argv ) if ( group != NULL ) properties = group; } + else if ( !strcmp( argv[ i ], "-attach" ) ) + { + mlt_filter filter = create_attach( field, argv[ ++ i ], track ); + if ( filter != NULL ) + { + if ( properties != NULL ) + mlt_service_attach( ( mlt_service )properties, filter ); + properties = mlt_filter_properties( filter ); + mlt_properties_inherit( properties, group ); + } + } else if ( !strcmp( argv[ i ], "-filter" ) ) { mlt_filter filter = create_filter( field, argv[ ++ i ], track ); diff --git a/src/modules/sdl/consumer_sdl.c b/src/modules/sdl/consumer_sdl.c index 06171b9..39b8894 100644 --- a/src/modules/sdl/consumer_sdl.c +++ b/src/modules/sdl/consumer_sdl.c @@ -121,6 +121,9 @@ mlt_consumer consumer_sdl_init( char *arg ) // Get sample aspect ratio this->aspect_ratio = mlt_properties_get_double( this->properties, "aspect_ratio" ); + + // Ensure we don't join on a non-running object + this->joined = 1; // Default display aspect ratio this->display_aspect = 4.0 / 3.0; @@ -178,6 +181,8 @@ int consumer_start( mlt_consumer parent ) { pthread_attr_t thread_attributes; + consumer_stop( parent ); + this->running = 1; this->joined = 0; diff --git a/src/modules/westley/consumer_westley.c b/src/modules/westley/consumer_westley.c index 4e8fbb0..cc02e99 100644 --- a/src/modules/westley/consumer_westley.c +++ b/src/modules/westley/consumer_westley.c @@ -188,7 +188,7 @@ static inline void serialise_properties( mlt_properties properties, xmlNode *nod } } -static inline void serialise_producer_filters( serialise_context context, mlt_service service, xmlNode *node ) +static inline void serialise_service_filters( serialise_context context, mlt_service service, xmlNode *node ) { int i; xmlNode *p; @@ -202,12 +202,13 @@ static inline void serialise_producer_filters( serialise_context context, mlt_se { // Get a new id - if already allocated, do nothing char *id = westley_get_id( context, mlt_filter_service( filter ), westley_filter ); - if ( id == NULL ) - continue; - - p = xmlNewChild( node, NULL, "filter", NULL ); - xmlNewProp( p, "id", id ); - serialise_properties( properties, p ); + if ( id != NULL ) + { + p = xmlNewChild( node, NULL, "filter", NULL ); + xmlNewProp( p, "id", id ); + serialise_properties( properties, p ); + serialise_service_filters( context, mlt_filter_service( filter ), p ); + } } } } @@ -229,7 +230,7 @@ static void serialise_producer( serialise_context context, mlt_service service, // Set the id xmlNewProp( child, "id", id ); serialise_properties( properties, child ); - serialise_producer_filters( context, service, child ); + serialise_service_filters( context, service, child ); // Add producer to the map mlt_properties_set_int( context->hide_map, id, mlt_properties_get_int( properties, "hide" ) ); @@ -280,7 +281,7 @@ static void serialise_multitrack( serialise_context context, mlt_service service if ( hide ) xmlNewProp( track, "hide", hide == 1 ? "video" : ( hide == 2 ? "audio" : "both" ) ); } - serialise_producer_filters( context, service, child ); + serialise_service_filters( context, service, child ); } } @@ -351,7 +352,7 @@ static void serialise_playlist( serialise_context context, mlt_service service, } } - serialise_producer_filters( context, service, child ); + serialise_service_filters( context, service, child ); } else if ( strcmp( (const char*) node->name, "tractor" ) != 0 ) { @@ -386,7 +387,7 @@ static void serialise_tractor( serialise_context context, mlt_service service, x // Recurse on connected producer serialise_service( context, mlt_service_producer( service ), child ); - serialise_producer_filters( context, service, child ); + serialise_service_filters( context, service, child ); } } @@ -413,6 +414,7 @@ static void serialise_filter( serialise_context context, mlt_service service, xm xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) ); serialise_properties( properties, child ); + serialise_service_filters( context, service, child ); } } @@ -439,6 +441,7 @@ static void serialise_transition( serialise_context context, mlt_service service xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) ); serialise_properties( properties, child ); + serialise_service_filters( context, service, child ); } } -- 1.7.4.4