Hi,

attached patch implement *matte* transition. it perform replacing alpha channel of track A with luma of track B. Luma of track B will be scaled if it required.

that patch helps to avoid using uncompressed BGRA video for CG.

test data could be downloaded from http://downloads.m1stereo.tv/8a1b443c948a9de6b6a32e665235de06/

if you need to prepare FILL and KEY (MATTE) files, you can use ffmpeg to extract alpha channel from existing video. For example:

extract alpha channel and video and create matte file:

ffmpeg -i sg_gm_2013_clip_title.avi -vf "alphaextract" -pix_fmt yuv422p -preset placebo -crf 10 -y sg_gm_2013_clip_title.matte_scaled.mp4

because of example above provides a scaled luma output, transition performs scaling (not SSE optimized) it from [16,235] -> [0, 255], it is possible to create unscaled (full) range:

ffmpeg -i sg_gm_2013_clip_title.avi -vf "alphaextract" -pix_fmt yuvj422p -preset placebo -crf 10 -y sg_gm_2013_clip_title.matte_full.mp4

fill track will be created similar:

ffmpeg -i sg_gm_2013_clip_title.avi -pix_fmt yuv422p -preset placebo -crf 10 -y sg_gm_2013_clip_title.fill.mp4

--
________________________________________
Maksym Veremeyenko
>From 26cf01645b9000b9229c476eec95ba4adb083cfc Mon Sep 17 00:00:00 2001
From: Maksym Veremeyenko <ve...@m1.tv>
Date: Tue, 24 Jun 2014 19:29:12 +0300
Subject: [PATCH] implement matte transition

---
 src/modules/core/Makefile             |    1 +
 src/modules/core/factory.c            |    3 +
 src/modules/core/transition_matte.c   |  177 +++++++++++++++++++++++++++++++++
 src/modules/core/transition_matte.yml |   12 +++
 4 files changed, 193 insertions(+), 0 deletions(-)
 create mode 100644 src/modules/core/transition_matte.c
 create mode 100644 src/modules/core/transition_matte.yml

diff --git a/src/modules/core/Makefile b/src/modules/core/Makefile
index f4b73f4..71bd848 100644
--- a/src/modules/core/Makefile
+++ b/src/modules/core/Makefile
@@ -39,6 +39,7 @@ OBJS = factory.o \
 	   transition_luma.o \
 	   transition_mix.o \
 	   transition_region.o \
+	   transition_matte.o \
 	   consumer_multi.o \
 	   consumer_null.o
 
diff --git a/src/modules/core/factory.c b/src/modules/core/factory.c
index 64b2fe2..86aaab3 100644
--- a/src/modules/core/factory.c
+++ b/src/modules/core/factory.c
@@ -56,6 +56,7 @@ extern mlt_producer producer_noise_init( mlt_profile profile, mlt_service_type t
 #include "transition_composite.h"
 extern mlt_transition transition_luma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_transition transition_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_transition transition_matte_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 #include "transition_region.h"
 
 static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
@@ -105,6 +106,7 @@ MLT_REPOSITORY
 	MLT_REGISTER( transition_type, "composite", transition_composite_init );
 	MLT_REGISTER( transition_type, "luma", transition_luma_init );
 	MLT_REGISTER( transition_type, "mix", transition_mix_init );
+	MLT_REGISTER( transition_type, "matte", transition_matte_init );
 	MLT_REGISTER( transition_type, "region", transition_region_init );
 
 	MLT_REGISTER_METADATA( consumer_type, "multi", metadata, "consumer_multi.yml" );
@@ -139,5 +141,6 @@ MLT_REPOSITORY
 	MLT_REGISTER_METADATA( transition_type, "composite", metadata, "transition_composite.yml" );
 	MLT_REGISTER_METADATA( transition_type, "luma", metadata, "transition_luma.yml" );
 	MLT_REGISTER_METADATA( transition_type, "mix", metadata, "transition_mix.yml" );
+	MLT_REGISTER_METADATA( transition_type, "matte", metadata, "transition_matte.yml" );
 	MLT_REGISTER_METADATA( transition_type, "region", metadata, "transition_region.yml" );
 }
diff --git a/src/modules/core/transition_matte.c b/src/modules/core/transition_matte.c
new file mode 100644
index 0000000..f1b9bdd
--- /dev/null
+++ b/src/modules/core/transition_matte.c
@@ -0,0 +1,177 @@
+/*
+ * transition_luma.c -- a generic dissolve/wipe processor
+ * Copyright (C) 2003-2014 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <d...@dennedy.org>
+ *
+ * Adapted from Kino Plugin Timfx, which is
+ * Copyright (C) 2002 Timothy M. Shead <tsh...@k-3d.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <framework/mlt.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include "transition_composite.h"
+
+typedef void ( *copy_luma_fn )(uint8_t* alpha_a, int stride_a, uint8_t* image_b, int stride_b, int width, int height);
+
+static void copy_Y_to_A_full_luma(uint8_t* alpha_a, int stride_a, uint8_t* image_b, int stride_b, int width, int height)
+{
+	int i, j;
+
+	for(j = 0; j < height; j++)
+	{
+		for(i = 0; i < width; i++)
+			alpha_a[i] = image_b[2*i];
+		alpha_a += stride_a;
+		image_b += stride_b;
+	};
+};
+
+static void copy_Y_to_A_scaled_luma(uint8_t* alpha_a, int stride_a, uint8_t* image_b, int stride_b, int width, int height)
+{
+	int i, j;
+
+	for(j = 0; j < height; j++)
+	{
+		for(i = 0; i < width; i++)
+		{
+			unsigned int p = image_b[2*i];
+
+			if(p < 16)
+				p = 16;
+			if(p > 235)
+				p = 235;
+			p = (p - 16) * 255 / 219;
+
+			alpha_a[i] = p;
+		};
+
+		alpha_a += stride_a;
+		image_b += stride_b;
+	};
+};
+
+/** Get the image.
+*/
+
+static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+	// Get the b frame from the stack
+	mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
+
+	// Get the transition object
+	mlt_transition transition = mlt_frame_pop_service( a_frame );
+
+//	mlt_service_lock( MLT_TRANSITION_SERVICE( transition ) );
+
+mlt_frame_get_image( a_frame, image, format, width, height, 1 );
+//	if ( b_frame == NULL )
+//	{
+//		
+//	}
+	if ( b_frame != NULL )
+	{
+		
+		// Get the properties of the transition
+		mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
+
+		// Get the properties of the a frame
+		mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
+
+		// Get the properties of the b frame
+		mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
+
+		int
+			width_a = mlt_properties_get_int( a_props, "width" ),
+			width_b = mlt_properties_get_int( b_props, "width" ),
+			height_a = mlt_properties_get_int( a_props, "height" ),
+			height_b = mlt_properties_get_int( b_props, "height" );
+
+		uint8_t *alpha_a, *image_b;
+
+		copy_luma_fn copy_luma = mlt_properties_get_int(b_props, "full_luma")?
+			copy_Y_to_A_full_luma:copy_Y_to_A_scaled_luma;
+
+		// This compositer is yuv422 only
+		*format = mlt_image_yuv422;
+
+		// Get the image from the a frame
+		mlt_frame_get_image( b_frame, &image_b, format, &width_b, &height_b, 1 );
+		alpha_a = mlt_frame_get_alpha_mask( a_frame );
+
+		// copy data
+		copy_luma
+		(
+			alpha_a, width_a, image_b, width_b * 2,
+			(width_a > width_b)?width_b:width_a,
+			(height_a > height_b)?height_b:height_a
+		);
+
+		// Extract the a_frame image info
+		*width = mlt_properties_get_int( a_props, "width" );
+		*height = mlt_properties_get_int( a_props, "height" );
+		*image = mlt_properties_get_data( a_props, "image", NULL );
+	};
+
+//	mlt_service_unlock( MLT_TRANSITION_SERVICE( transition ) );
+
+	return 0;
+}
+
+
+/** Matte transition processing.
+*/
+
+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, transition );
+
+	// Push the b_frame on to the stack
+	mlt_frame_push_frame( a_frame, b_frame );
+
+	// Push the transition method
+	mlt_frame_push_get_image( a_frame, transition_get_image );
+	
+	return a_frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_transition transition_matte_init( mlt_profile profile, mlt_service_type type, const char *id, char *lumafile )
+{
+	mlt_transition transition = mlt_transition_new( );
+	if ( transition != NULL )
+	{
+		// Set the methods
+		transition->process = transition_process;
+		
+		// Default factory
+		mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "factory", mlt_environment( "MLT_PRODUCER" ) );
+
+		// Inform apps and framework that this is a video only transition
+		mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 1 );
+
+		return transition;
+	}
+	return NULL;
+}
diff --git a/src/modules/core/transition_matte.yml b/src/modules/core/transition_matte.yml
new file mode 100644
index 0000000..4c7f19f
--- /dev/null
+++ b/src/modules/core/transition_matte.yml
@@ -0,0 +1,12 @@
+schema_version: 0.1
+type: transition
+identifier: matte
+title: Matte
+version: 1
+copyright: Ushodaya Enterprises Limited
+creator: Dan Dennedy
+license: LGPLv2.1
+language: en
+tags:
+  - Video
+description: Replace alphachannel with data from luma channel of other track.
-- 
1.7.7.6

------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Mlt-devel mailing list
Mlt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlt-devel

Reply via email to