]> git.sesse.net Git - mlt/commitdiff
Filter attachments to services
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Mon, 6 Sep 2004 12:14:09 +0000 (12:14 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Mon, 6 Sep 2004 12:14:09 +0000 (12:14 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@409 d19143bc-622f-0410-bfdd-b5b2a6649095

src/framework/mlt_producer.c
src/framework/mlt_service.c
src/framework/mlt_service.h
src/inigo/inigo.c
src/modules/core/filter_region.c
src/modules/core/filter_watermark.c
src/modules/core/transition_region.c
src/modules/dv/producer_libdv.c
src/modules/inigo/producer_inigo.c
src/modules/sdl/consumer_sdl.c
src/modules/westley/consumer_westley.c

index 4fda305526c0d8a056de87431d23b0a00dd82f19..acfaad1bb4b5ba081554193e0ad2442cc3711ba3 100644 (file)
@@ -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 )
index 6df363064cebcd5534d3c38c35bd2fc9002ef665..0851b9ae52b8496efdb6dd966ec543a6507bb2f4 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "config.h"
 #include "mlt_service.h"
+#include "mlt_filter.h"
 #include "mlt_frame.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -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 );
                }
        }
index a4a1ee0eed3ce32ccb86090930bf1b5c3d809de7..47cd929c2f63886511968268ba0973f159115dd7 100644 (file)
@@ -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)
index 41a03415ef1f7de481cd90dd9114ebe23e184449..91b283a3a90b48b856de963157ee032c1d5d7973 100644 (file)
@@ -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"
index 635b3907e85600c111326b3525f18522a98f4221..db69b661f193004dc1e2d48cbb12c746206ffce6 100644 (file)
@@ -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
index afe036e4c7540925c917e345cfb368b671e9d8c8..883db6928995884c09e36633a870785c7af786c5 100644 (file)
@@ -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 );
index e8391c5ce8e284f613151cc4c9381bcf86d181b4..aa7b660aeb388ad29520f9c5877aa2ce55b09f39 100644 (file)
@@ -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 );
 
index 4abf75ae17c7e405195c9ceb49c8703e36ee1ef1..7a0c16bc1e258efc7145997f822471a9ebccd4b6 100644 (file)
@@ -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
                        {
index 9dc560e21856579087d6569aa4e4f78d8d2ef2fc..83434cf8b1fe3aa4074fc6c70cb9e3fe6f05427e 100644 (file)
@@ -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 );
index 06171b9cfaab2f092e0573a38c428a68e6a7bafc..39b8894bd94e7bfda76264e8d60d1f520f22fef1 100644 (file)
@@ -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;
 
index 4e8fbb045693f4c0dcac8a49e7ffb5b572278c6d..cc02e9933e77290b2a2d44e0df98614f8cc0fcff 100644 (file)
@@ -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 );
        }
 }