Hi.

For a long time, i wanted to introduce the region filter in Kdenlive. I am 
almost ready on the Kdenlive GUI side, and here is the patch that fixes 
several issues (mem leak & other problems) in the MLT region filter / 
transition.

This patch makes the region filter work fine for me in multitrack playlists. 
Not sure about using the transition region alone as I never really managed to 
make it work, but my patch shouldn't make it worse..

For those not knowing it, a region filter example:

melt color:blue -attach region:+hello.txt in=0 out=200 a_track=0 b_track=1 
filter0=sepia

will apply a sepia filter on a zone defined by the text "hello" over the blue 
clip.


regards
jb
diff --git a/src/modules/core/filter_region.c b/src/modules/core/filter_region.c
index 8fd8e8d..16bc43b 100644
--- a/src/modules/core/filter_region.c
+++ b/src/modules/core/filter_region.c
@@ -30,10 +30,16 @@
 /** Filter processing.
 */
 
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+
+static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
+	// Get the filter
+	mlt_filter this = mlt_frame_pop_service( frame );
+
 	// Get the properties of the filter
 	mlt_properties properties = MLT_FILTER_PROPERTIES( this );
+	
+	mlt_service_lock( MLT_FILTER_SERVICE( this ) );
 
 	// Get the region transition
 	mlt_transition transition = mlt_properties_get_data( properties, "_transition", NULL );
@@ -51,14 +57,32 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 		// Pass a reference to this filter down
 		mlt_properties_set_data( MLT_TRANSITION_PROPERTIES( transition ), "_region_filter", this, 0, NULL, NULL );
 	}
+	
+	mlt_service_unlock( MLT_FILTER_SERVICE( this ) );
 
 	// Pass all properties down
 	mlt_properties_pass( MLT_TRANSITION_PROPERTIES( transition ), properties, "" );
-
+	
+	mlt_position position = mlt_filter_get_position( this, frame );
+		
+	mlt_frame_set_position( frame, position );
+	
 	// Process the frame
-	return mlt_transition_process( transition, frame, NULL );
+	mlt_transition_process( transition, frame, NULL );
+	
+	return mlt_frame_get_image( frame, image, format, width, height, writable );
+}
+
+static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+{
+  
+  	mlt_frame_push_service( frame, this );
+	mlt_frame_push_get_image( frame, filter_get_image );
+
+	return frame;
 }
 
+
 /** Constructor for the filter.
 */
 
diff --git a/src/modules/core/transition_region.c b/src/modules/core/transition_region.c
index 4486d23..9df4e6d 100644
--- a/src/modules/core/transition_region.c
+++ b/src/modules/core/transition_region.c
@@ -111,26 +111,27 @@ static uint8_t *filter_get_alpha_mask( mlt_frame this )
 	mlt_frame_get_image( shape_frame, &image, &format, &region_width, &region_height, 0 );
 
 	alpha = mlt_frame_get_alpha_mask( shape_frame );
+	
+	int size = region_width * region_height;
+	uint8_t *alpha_duplicate = mlt_pool_alloc( size );
 
 	// Generate from the Y component of the image if no alpha available
 	if ( alpha == NULL )
 	{
-		int size = region_width * region_height;
-		uint8_t *p = mlt_pool_alloc( size );
-		alpha = p;
 		while ( size -- )
 		{
-			*p ++ = ( int )( ( ( *image ++ - 16 ) * 299 ) / 255 );
+			*alpha_duplicate ++ = ( int )( ( ( *image ++ - 16 ) * 299 ) / 255 );
 			image ++;
 		}
-		mlt_frame_set_alpha( this, alpha, region_width * region_height, mlt_pool_release );
+		
 	}
 	else
 	{
-		mlt_frame_set_alpha( this, alpha, region_width * region_height, NULL );
+		// Duplicate alpha
+                memcpy( alpha_duplicate, alpha, size );
 	}
 
-	return alpha;
+	return alpha_duplicate;
 }
 
 /** Do it :-).
@@ -149,6 +150,9 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 
 	// Get the properties of the transition
 	mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+	
+	// Get the properties of the a frame
+	mlt_properties a_props = MLT_FRAME_PROPERTIES( frame );	
 
 	mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
 
@@ -262,8 +266,8 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 		}
 	}
 
-	mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "width", *width );
-	mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "height", *height );
+	mlt_properties_set_int( a_props, "width", *width );
+	mlt_properties_set_int( a_props, "height", *height );
 
 	// Only continue if we have both filter and composite
 	if ( composite != NULL )
@@ -279,25 +283,35 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 
 		// Index to hold the count
 		int i = 0;
+		
+		mlt_properties b_props;
 
 		// We will get the 'b frame' from the composite only if it's NULL (region filter)
 		if ( b_frame == NULL )
 		{
 			// Copy the region
 			b_frame = composite_copy_region( composite, frame, position );
-
+			
+			// Get the properties of the b frame
+			b_props = MLT_FRAME_PROPERTIES( b_frame );
+			
 			// Ensure a destructor
 			char *name = mlt_properties_get( properties, "_unique_id" );
-			mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), name, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
+			mlt_properties_set_data( a_props, name, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
+			
+			// Filter only, we want to composite over itself
+			if ( mlt_properties_get_int( properties, "filter_only" ) )
+			{
+				frame = composite_copy_region( composite, b_frame, position );
+				mlt_properties_set_data( MLT_FRAME_PROPERTIES( b_frame ), name, frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
+			}
 		}
-
-		// filter_only prevents copying the alpha channel of the shape to the output frame
-		// by compositing filtered frame over itself
-		if ( mlt_properties_get_int( properties, "filter_only" ) )
+		else
 		{
-			frame = composite_copy_region( composite, b_frame, position );
+			// Get the properties of the b frame
+			b_props = MLT_FRAME_PROPERTIES( b_frame );
 		}
-
+		
 		// Make sure the filter is in the correct position
 		while ( filter != NULL )
 		{
@@ -311,18 +325,19 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 			// Get the next filter
 			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 )
 			mlt_service_apply_filters( MLT_FILTER_SERVICE( filter ), b_frame, 0 );
 
+
 		// Hmm - this is probably going to go wrong....
 		mlt_frame_set_position( frame, position );
-
+		
 		// Get the b frame and process with composite if successful
 		mlt_transition_process( composite, frame, b_frame );
-
+		
 		// If we have a shape producer copy the alpha mask from the shape frame to the b_frame
 		if ( strcmp( resource, "rectangle" ) != 0 )
 		{
@@ -376,14 +391,14 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 				if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &shape_frame, 0 ) == 0 )
 				{
 					// Ensure that the shape frame will be closed
-					mlt_properties_set_data( MLT_FRAME_PROPERTIES( b_frame ), "shape_frame", shape_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
+					mlt_properties_set_data( b_props, "shape_frame", shape_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
 
 					// Specify the callback for evaluation
 					b_frame->get_alpha_mask = filter_get_alpha_mask;
 				}
 			}
 		}
-
+		
 		// Get the image
 		error = mlt_frame_get_image( frame, image, format, width, height, 0 );
 	}
@@ -396,10 +411,10 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 /** Filter processing.
 */
 
-static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
+static mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
 {
 	// Push the transition on to the frame
-	mlt_frame_push_service( a_frame, this );
+	mlt_frame_push_service( a_frame, transition );
 
 	// Push the b_frame on to the stack
 	mlt_frame_push_frame( a_frame, b_frame );
@@ -417,16 +432,16 @@ static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt
 mlt_transition transition_region_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
 	// Create a new transition
-	mlt_transition this = mlt_transition_new( );
+	mlt_transition transition = mlt_transition_new( );
 
 	// Further initialisation
-	if ( this != NULL )
+	if ( transition != NULL )
 	{
 		// Get the properties from the transition
-		mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+		mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
 
 		// Assign the transition process method
-		this->process = transition_process;
+		transition->process = transition_process;
 
 		// Default factory
 		mlt_properties_set( properties, "factory", mlt_environment( "MLT_PRODUCER" ) );
@@ -439,6 +454,6 @@ mlt_transition transition_region_init( mlt_profile profile, mlt_service_type typ
 	}
 
 	// Return the transition
-	return this;
+	return transition;
 }
 
------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
Mlt-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mlt-devel

Reply via email to