From 36aad7b318537612374acfd3f626a8c1364ad95d Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Sun, 8 Feb 2004 14:29:40 +0000 Subject: [PATCH] pixbuf, composite and fezzik mirrors git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@124 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/framework/mlt_properties.c | 36 +++++ src/framework/mlt_properties.h | 1 + src/modules/core/transition_composite.c | 24 +++ src/modules/fezzik/producer_fezzik.c | 3 + src/modules/gtk2/filter_rescale.c | 2 +- src/modules/gtk2/producer_pango.c | 38 +++-- src/modules/gtk2/producer_pixbuf.c | 242 +++++++++++++++---------------- 7 files changed, 207 insertions(+), 139 deletions(-) diff --git a/src/framework/mlt_properties.c b/src/framework/mlt_properties.c index be4d66f..27f4a27 100644 --- a/src/framework/mlt_properties.c +++ b/src/framework/mlt_properties.c @@ -72,6 +72,30 @@ mlt_properties mlt_properties_new( ) return this; } +/** Special case - when a container (such as fezzik) is protecting another + producer, we need to ensure that properties are passed through to the + real producer. +*/ + +static void mlt_properties_do_mirror( mlt_properties this, char *name ) +{ + mlt_properties mirror = mlt_properties_get_data( this, "mlt_mirror", NULL ); + if ( mirror != NULL ) + { + char *value = mlt_properties_get( this, name ); + if ( value != NULL ) + mlt_properties_set( mirror, name, value ); + } +} + +/** Allow the specification of a mirror. +*/ + +void mlt_properties_mirror( mlt_properties this, mlt_properties that ) +{ + mlt_properties_set_data( this, "mlt_mirror", that, 0, NULL, NULL ); +} + /** Inherit all serialisable properties from that into this. */ @@ -158,7 +182,10 @@ int mlt_properties_set( mlt_properties this, char *name, char *value ) // Set it if not NULL if ( property != NULL ) + { error = mlt_property_set_string( property, value ); + mlt_properties_do_mirror( this, name ); + } return error; } @@ -251,7 +278,10 @@ int mlt_properties_set_int( mlt_properties this, char *name, int value ) // Set it if not NULL if ( property != NULL ) + { error = mlt_property_set_int( property, value ); + mlt_properties_do_mirror( this, name ); + } return error; } @@ -277,7 +307,10 @@ int mlt_properties_set_double( mlt_properties this, char *name, double value ) // Set it if not NULL if ( property != NULL ) + { error = mlt_property_set_double( property, value ); + mlt_properties_do_mirror( this, name ); + } return error; } @@ -303,7 +336,10 @@ int mlt_properties_set_position( mlt_properties this, char *name, mlt_position v // Set it if not NULL if ( property != NULL ) + { error = mlt_property_set_position( property, value ); + mlt_properties_do_mirror( this, name ); + } return error; } diff --git a/src/framework/mlt_properties.h b/src/framework/mlt_properties.h index 2cacc9f..1527f38 100644 --- a/src/framework/mlt_properties.h +++ b/src/framework/mlt_properties.h @@ -38,6 +38,7 @@ struct mlt_properties_s extern int mlt_properties_init( mlt_properties, void *child ); extern mlt_properties mlt_properties_new( ); +extern void mlt_properties_mirror( mlt_properties this, mlt_properties that ); extern int mlt_properties_inherit( mlt_properties this, mlt_properties that ); extern int mlt_properties_set( mlt_properties this, char *name, char *value ); extern int mlt_properties_parse( mlt_properties this, char *namevalue ); diff --git a/src/modules/core/transition_composite.c b/src/modules/core/transition_composite.c index 2903bb0..106b193 100644 --- a/src/modules/core/transition_composite.c +++ b/src/modules/core/transition_composite.c @@ -108,8 +108,32 @@ static int composite_yuv( uint8_t *p_dest, mlt_image_format format_dest, int wid int width_src = ( int )( ( float )width_dest * geometry.w / 100 ); int height_src = ( int )( ( float )height_dest * geometry.h / 100 ); + mlt_properties b_props = mlt_frame_properties( that ); + mlt_transition this = mlt_properties_get_data( b_props, "transition_composite", NULL ); + mlt_properties properties = mlt_transition_properties( this ); + + if ( mlt_properties_get( properties, "distort" ) == NULL && + mlt_properties_get( mlt_frame_properties( that ), "real_width" ) != NULL ) + { + int width_b = mlt_properties_get_int( mlt_frame_properties( that ), "real_width" ); + int height_b = mlt_properties_get_int( mlt_frame_properties( that ), "real_height" ); + + if ( width_b < width_src ) + width_src = width_b; + if ( height_b < height_src ) + height_src = height_b; + mlt_properties_set( mlt_frame_properties( that ), "rescale.interp", "none" ); + } + else if ( mlt_properties_get( mlt_frame_properties( that ), "real_width" ) != NULL ) + { + mlt_properties_set( mlt_frame_properties( that ), "rescale.interp", "none" ); + } + x -= x % 2; + if ( width_src <= 0 || height_src <= 0 ) + return ret; + // optimization point - no work to do if ( ( x < 0 && -x >= width_src ) || ( y < 0 && -y >= height_src ) ) return ret; diff --git a/src/modules/fezzik/producer_fezzik.c b/src/modules/fezzik/producer_fezzik.c index 4ff34eb..bd43e1c 100644 --- a/src/modules/fezzik/producer_fezzik.c +++ b/src/modules/fezzik/producer_fezzik.c @@ -149,6 +149,9 @@ mlt_producer producer_fezzik_init( char *arg ) // and fezzik doesn't overdo it with throwing rocks... mlt_properties_set( properties, "westley", "was here" ); + // We need to ensure that all further properties are mirrored in the producer + mlt_properties_mirror( properties, mlt_producer_properties( producer ) ); + // Now, we return the producer of the tractor producer = mlt_tractor_producer( tractor ); } diff --git a/src/modules/gtk2/filter_rescale.c b/src/modules/gtk2/filter_rescale.c index d9c7f83..f061038 100644 --- a/src/modules/gtk2/filter_rescale.c +++ b/src/modules/gtk2/filter_rescale.c @@ -71,7 +71,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * #endif // If width and height are correct, don't do anything - if ( input != NULL && ( iwidth != owidth || iheight != oheight ) ) + if ( strcmp( interps, "none" ) && input != NULL && ( iwidth != owidth || iheight != oheight ) ) { if ( *format == mlt_image_yuv422 ) { diff --git a/src/modules/gtk2/producer_pango.c b/src/modules/gtk2/producer_pango.c index 1b30743..5232389 100644 --- a/src/modules/gtk2/producer_pango.c +++ b/src/modules/gtk2/producer_pango.c @@ -88,6 +88,16 @@ mlt_producer producer_pango_init( const char *filename ) mlt_properties_set( properties, "resource", "pango" ); mlt_properties_set( properties, "markup", "" ); } + else if ( filename[ 0 ] == '+' ) + { + char *markup = strdup( filename + 1 ); + ( *strrchr( markup, '.' ) ) = '\0'; + while ( strchr( markup, '~' ) ) + ( *strchr( markup, '~' ) ) = '\n'; + mlt_properties_set( properties, "resource", ( char * )filename ); + mlt_properties_set( properties, "markup", markup ); + free( markup ); + } else { FILE *f = fopen( filename, "r" ); @@ -112,10 +122,13 @@ mlt_producer producer_pango_init( const char *filename ) } } fclose( f ); + + if ( markup[ strlen( markup ) - 1 ] == '\n' ) + markup[ strlen( markup ) - 1 ] = '\0'; + mlt_properties_set( properties, "resource", ( char * ) filename ); mlt_properties_set( properties, "markup", ( char * ) ( markup == NULL ? "" : markup ) ); - if ( markup ) - free( markup ); + free( markup ); } else { @@ -211,12 +224,15 @@ static void refresh_image( mlt_frame frame, int width, int height ) // Register this pixbuf for destruction and reuse mlt_properties_set_data( producer_props, "pixbuf", pixbuf, 0, ( mlt_destructor )g_object_unref, NULL ); + mlt_properties_set_int( producer_props, "real_width", gdk_pixbuf_get_width( pixbuf ) ); + mlt_properties_set_int( producer_props, "real_height", gdk_pixbuf_get_height( pixbuf ) ); + // Store the width/height of the pixbuf temporarily this->width = gdk_pixbuf_get_width( pixbuf ); this->height = gdk_pixbuf_get_height( pixbuf ); } } - else if ( width != this->width || height != this->height ) + else if ( this->image == NULL || width != this->width || height != this->height ) { pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL ); } @@ -224,15 +240,8 @@ static void refresh_image( mlt_frame frame, int width, int height ) // If we have a pixbuf and a valid width if ( pixbuf && width > 0 ) { - int delete = 0; - - // Scale to width/height requested - if ( width != this->width && height != this->height ) - { - // Note - the original pixbuf is already safe and ready for destruction - pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_HYPER ); - delete = 1; - } + // Note - the original pixbuf is already safe and ready for destruction + pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_HYPER ); // Store width and height this->width = gdk_pixbuf_get_width( pixbuf ); @@ -264,8 +273,7 @@ static void refresh_image( mlt_frame frame, int width, int height ) } // Finished with pixbuf now - if ( delete ) - g_object_unref( pixbuf ); + g_object_unref( pixbuf ); // if single picture, reference the image and alpha in the producer free( this->image ); @@ -277,6 +285,8 @@ static void refresh_image( mlt_frame frame, int width, int height ) // Set width/height mlt_properties_set_int( properties, "width", this->width ); mlt_properties_set_int( properties, "height", this->height ); + mlt_properties_set_int( properties, "real_width", mlt_properties_get_int( producer_props, "real_width" ) ); + mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "real_height" ) ); // pass the image and alpha data without destructor mlt_properties_set_data( properties, "image", this->image, this->width * this->height * 2, NULL, NULL ); diff --git a/src/modules/gtk2/producer_pixbuf.c b/src/modules/gtk2/producer_pixbuf.c index 81255d7..699550d 100644 --- a/src/modules/gtk2/producer_pixbuf.c +++ b/src/modules/gtk2/producer_pixbuf.c @@ -65,7 +65,7 @@ mlt_producer producer_pixbuf_init( char *filename ) // Set the default properties mlt_properties_set( properties, "resource", filename ); mlt_properties_set_int( properties, "video_standard", mlt_video_standard_pal ); - mlt_properties_set_double( properties, "ttl", 5 ); + mlt_properties_set_int( properties, "ttl", 25 ); // Obtain filenames if ( strchr( filename, '%' ) != NULL ) @@ -117,7 +117,6 @@ mlt_producer producer_pixbuf_init( char *filename ) free( de[ i ] ); } - mlt_properties_set_position( properties, "out", this->count * 25 ); free( de ); free( dir_name ); } @@ -137,139 +136,73 @@ mlt_producer producer_pixbuf_init( char *filename ) return NULL; } -static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) -{ - // Obtain properties of frame - mlt_properties properties = mlt_frame_properties( this ); - - // May need to know the size of the image to clone it - int size = 0; - - // Get the image - uint8_t *image = mlt_properties_get_data( properties, "image", &size ); - - // Get width and height - *width = mlt_properties_get_int( properties, "width" ); - *height = mlt_properties_get_int( properties, "height" ); - - // Clone if necessary - // NB: Cloning is necessary with this producer (due to processing of images ahead of use) - // The fault is not in the design of mlt, but in the implementation of pixbuf... - //if ( writable ) - { - size = *width * *height * 2; - - // Clone our image - uint8_t *copy = malloc( size ); - memcpy( copy, image, size ); - - // We're going to pass the copy on - image = copy; - - // Now update properties so we free the copy after - mlt_properties_set_data( properties, "image", copy, size, free, NULL ); - } - - // Pass on the image - *buffer = image; - - return 0; -} - -static uint8_t *producer_get_alpha_mask( mlt_frame this ) +static void refresh_image( mlt_frame frame, int width, int height ) { - // Obtain properties of frame - mlt_properties properties = mlt_frame_properties( this ); - - // Return the alpha mask - return mlt_properties_get_data( properties, "alpha", NULL ); -} - -static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) -{ - producer_pixbuf this = producer->child; + // Pixbuf GdkPixbuf *pixbuf = NULL; GError *error = NULL; - // Generate a frame - *frame = mlt_frame_init( ); - // Obtain properties of frame - mlt_properties properties = mlt_frame_properties( *frame ); + mlt_properties properties = mlt_frame_properties( frame ); + + // Obtain the producer pango for this frame + producer_pixbuf this = mlt_properties_get_data( properties, "producer_pixbuf", NULL ); + + // Obtain the producer + mlt_producer producer = &this->parent; // Obtain properties of producer mlt_properties producer_props = mlt_producer_properties( producer ); // Get the time to live for each frame - double ttl = mlt_properties_get_double( producer_props, "ttl" ); + double ttl = mlt_properties_get_int( producer_props, "ttl" ); // Image index int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count; // Update timecode on the frame we're creating - mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( frame, mlt_producer_position( producer ) ); // optimization for subsequent iterations on single picture if ( this->image != NULL && image_idx == this->image_idx ) { - // Set width/height - mlt_properties_set_int( properties, "width", this->width ); - mlt_properties_set_int( properties, "height", this->height ); - - // Set the compositing properties - if ( mlt_properties_get( producer_props, "x" ) != NULL ) - mlt_properties_set_int( properties, "x", mlt_properties_get_int( producer_props, "x" ) ); - if ( mlt_properties_get( producer_props, "y" ) != NULL ) - mlt_properties_set_int( properties, "y", mlt_properties_get_int( producer_props, "y" ) ); - if ( mlt_properties_get( producer_props, "mix" ) != NULL ) - mlt_properties_set_double( properties, "image.mix", mlt_properties_get_double( producer_props, "mix" ) ); - - // if picture sequence pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL ); - - // Set alpha mask call back - ( *frame )->get_alpha_mask = producer_get_alpha_mask; - - // Stack the get image callback - mlt_frame_push_get_image( *frame, producer_get_image ); + if ( width != this->width || height != this->height ) + { + pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL ); + } } else { free( this->image ); + this->image = NULL; free( this->alpha ); + this->alpha = NULL; this->image_idx = image_idx; pixbuf = gdk_pixbuf_new_from_file( this->filenames[ image_idx ], &error ); + + if ( pixbuf != NULL ) + { + // Register this pixbuf for destruction and reuse + mlt_properties_set_data( producer_props, "pixbuf", pixbuf, 0, ( mlt_destructor )g_object_unref, NULL ); + + mlt_properties_set_int( producer_props, "real_width", gdk_pixbuf_get_width( pixbuf ) ); + mlt_properties_set_int( producer_props, "real_height", gdk_pixbuf_get_height( pixbuf ) ); + + // Store the width/height of the pixbuf temporarily + this->width = gdk_pixbuf_get_width( pixbuf ); + this->height = gdk_pixbuf_get_height( pixbuf ); + } } // If we have a pixbuf - if ( pixbuf ) + if ( pixbuf && width > 0 ) { - // Scale to adjust for sample aspect ratio - if ( mlt_properties_get_int( properties, "video_standard" ) == mlt_video_standard_pal ) - { - GdkPixbuf *temp = pixbuf; - GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf, - (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 45.0/48.0), - gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER ); - pixbuf = scaled; - g_object_unref( temp ); - } - else - { - GdkPixbuf *temp = pixbuf; - GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf, - (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 9.0/8.0 ), - gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER ); - pixbuf = scaled; - g_object_unref( temp ); - } + // Note - the original pixbuf is already safe and ready for destruction + pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, GDK_INTERP_HYPER ); // Store width and height this->width = gdk_pixbuf_get_width( pixbuf ); this->height = gdk_pixbuf_get_height( pixbuf ); - this->width -= this->width % 4; - this->height -= this->height % 2; // Allocate/define image and alpha uint8_t *image = malloc( this->width * this->height * 2 ); @@ -299,33 +232,96 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Finished with pixbuf now g_object_unref( pixbuf ); - // Set width/height of frame - mlt_properties_set_int( properties, "width", this->width ); - mlt_properties_set_int( properties, "height", this->height ); - - // Set the compositing properties - if ( mlt_properties_get( producer_props, "x" ) != NULL ) - mlt_properties_set_int( properties, "x", mlt_properties_get_int( producer_props, "x" ) ); - if ( mlt_properties_get( producer_props, "y" ) != NULL ) - mlt_properties_set_int( properties, "y", mlt_properties_get_int( producer_props, "y" ) ); - if ( mlt_properties_get( producer_props, "mix" ) != NULL ) - mlt_properties_set_double( properties, "mix", mlt_properties_get_double( producer_props, "mix" ) ); - // Pass alpha and image on properties with or without destructor this->image = image; this->alpha = alpha; + } - // pass the image and alpha data without destructor - mlt_properties_set_data( properties, "image", image, this->width * this->height * 2, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, this->width * this->height, NULL, NULL ); + // Set width/height of frame + mlt_properties_set_int( properties, "width", this->width ); + mlt_properties_set_int( properties, "height", this->height ); + mlt_properties_set_int( properties, "real_width", mlt_properties_get_int( producer_props, "real_width" ) ); + mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "real_height" ) ); + + // pass the image and alpha data without destructor + mlt_properties_set_data( properties, "image", this->image, this->width * this->height * 2, NULL, NULL ); + mlt_properties_set_data( properties, "alpha", this->alpha, this->width * this->height, NULL, NULL ); +} + +static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) +{ + // Obtain properties of frame + mlt_properties properties = mlt_frame_properties( frame ); + + // Refresh the image + refresh_image( frame, *width, *height ); + + // May need to know the size of the image to clone it + int size = 0; + + // Get the image + uint8_t *image = mlt_properties_get_data( properties, "image", &size ); - // Set alpha call back - ( *frame )->get_alpha_mask = producer_get_alpha_mask; + // Get width and height + *width = mlt_properties_get_int( properties, "width" ); + *height = mlt_properties_get_int( properties, "height" ); + + // Clone if necessary + // NB: Cloning is necessary with this producer (due to processing of images ahead of use) + // The fault is not in the design of mlt, but in the implementation of pixbuf... + //if ( writable ) + { + size = *width * *height * 2; + + // Clone our image + uint8_t *copy = malloc( size ); + memcpy( copy, image, size ); + + // We're going to pass the copy on + image = copy; - // Push the get_image method - mlt_frame_push_get_image( *frame, producer_get_image ); + // Now update properties so we free the copy after + mlt_properties_set_data( properties, "image", copy, size, free, NULL ); } + // Pass on the image + *buffer = image; + + return 0; +} + +static uint8_t *producer_get_alpha_mask( mlt_frame this ) +{ + // Obtain properties of frame + mlt_properties properties = mlt_frame_properties( this ); + + // Return the alpha mask + return mlt_properties_get_data( properties, "alpha", NULL ); +} + +static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) +{ + // Get the real structure for this producer + producer_pixbuf this = producer->child; + + // Generate a frame + *frame = mlt_frame_init( ); + + // Obtain properties of frame and producer + mlt_properties properties = mlt_frame_properties( *frame ); + + // Set the producer on the frame properties + mlt_properties_set_data( properties, "producer_pixbuf", this, 0, NULL, NULL ); + + // Refresh the pango image + refresh_image( *frame, 0, 0 ); + + // Set alpha call back + ( *frame )->get_alpha_mask = producer_get_alpha_mask; + + // Push the get_image method + mlt_frame_push_get_image( *frame, producer_get_image ); + // Calculate the next timecode mlt_producer_prepare_next( producer ); @@ -335,10 +331,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i static void producer_close( mlt_producer parent ) { producer_pixbuf this = parent->child; - if ( this->image ) - free( this->image ); - if ( this->alpha ) - free( this->alpha ); + free( this->image ); + free( this->alpha ); parent->close = NULL; mlt_producer_close( parent ); free( this ); -- 1.7.4.4