--- /dev/null
+include ../../../config.mak
+
+TARGET = ../libmltfrei0r$(LIBSUF)
+
+OBJS = factory.o \
+ filter_frei0r.o \
+ transition_frei0r.o \
+ frei0r_helper.o
+
+CFLAGS += -I../..
+
+LDFLAGS += -lm
+
+LDFLAGS+=-L../../framework -lmlt
+
+SRCS := $(OBJS:.o=.c)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
+
+depend: $(SRCS)
+ $(CC) -MM $(CFLAGS) $^ 1>.depend
+
+distclean: clean
+ rm -f .depend
+
+clean:
+ rm -f $(OBJS) $(TARGET)
+
+install: all
+ install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
--- /dev/null
+#! /bin/sh
+
+if [ "$help" != "1" ]
+then
+
+ echo -e "#include <frei0r.h>\n void main(){}\n"| gcc - -E -o /dev/null >/dev/null 2>&1
+
+ if [ "$?" = "1" ]
+ then
+ touch ../disable-frei0r
+ echo "- frei0r plugin disabled. Install frei0r-plugins and make sure frei0r.h is available."
+ fi
+
+fi
--- /dev/null
+/*
+ * factory.c -- the factory method interfaces
+ * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
+ *
+ * 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 <string.h>
+#include <framework/mlt.h>
+#include <frei0r.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+extern mlt_filter filter_frei0r_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_frame filter_process( mlt_filter this, mlt_frame frame );
+extern void filter_close( mlt_filter this );
+extern void transition_close( mlt_transition this );
+extern mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame );
+
+void fill_param_info ( mlt_repository repository , void* handle, f0r_plugin_info_t* info , mlt_service_type type , char* name ) {
+
+ int j=0;
+ void (*param_info)(f0r_param_info_t*,int param_index)=dlsym(handle,"f0r_get_param_info");
+ mlt_properties metadata_properties=NULL;
+ switch (type){
+ case filter_type:
+ metadata_properties=mlt_repository_filters(repository);
+ break;
+ default:
+ metadata_properties=NULL;
+ }
+
+ if (!metadata_properties){
+ return;
+ }
+
+ mlt_properties this_item_properties = mlt_properties_get_data( metadata_properties , name , NULL );
+ mlt_properties metadata = mlt_properties_get_data( this_item_properties , "metadata" , NULL );
+ if (!metadata){
+ metadata = mlt_properties_new( );
+ mlt_properties_set_data( this_item_properties , "metadata" , metadata , 0 , NULL, NULL );
+ }
+ char descstr[2048];
+ snprintf ( descstr, 2048 , "%s (Version: %d.%d)" , info->explanation , info->major_version , info->minor_version );
+ mlt_properties_set ( metadata, "title" , info->name );
+ mlt_properties_set ( metadata, "identifier" , name );
+ mlt_properties_set ( metadata, "description" , descstr );
+ mlt_properties_set ( metadata, "creator" , info->author );
+
+ mlt_properties parameter = mlt_properties_get_data( metadata , "parameters" , NULL );
+
+ if (!parameter){
+ parameter = mlt_properties_new ( );
+ mlt_properties_set_data ( metadata , "parameters" , parameter , 0 , NULL, NULL );
+ }
+
+ char numstr[512];
+
+ for (j=0;j<info->num_params;j++){
+ snprintf ( numstr , 512 , "%d" , j );
+ mlt_properties pnum = mlt_properties_get_data( metadata , numstr , NULL );
+ if (!pnum){
+ pnum = mlt_properties_new ( );
+ mlt_properties_set_data ( parameter , numstr , pnum , 0 , NULL, NULL );
+ }
+
+ f0r_param_info_t paraminfo;
+ param_info(¶minfo,j);
+ mlt_properties_set ( pnum , "identifier" , paraminfo.name );
+ mlt_properties_set ( pnum , "title" , paraminfo.name );
+ mlt_properties_set ( pnum , "description" , paraminfo.explanation);
+
+ if ( paraminfo.type == F0R_PARAM_DOUBLE ){
+ mlt_properties_set ( pnum , "type" , "integer" );
+ mlt_properties_set ( pnum , "minimum" , "0" );
+ mlt_properties_set ( pnum , "maximum" , "1000" );
+ mlt_properties_set ( pnum , "readonly" , "no" );
+ mlt_properties_set ( pnum , "widget" , "spinner" );
+ }else
+ if ( paraminfo.type == F0R_PARAM_BOOL ){
+ mlt_properties_set ( pnum , "type" , "boolean" );
+ mlt_properties_set ( pnum , "minimum" , "0" );
+ mlt_properties_set ( pnum , "maximum" , "1" );
+ mlt_properties_set ( pnum , "readonly" , "no" );
+ }else
+ if ( paraminfo.type == F0R_PARAM_STRING ){
+ mlt_properties_set ( pnum , "type" , "string" );
+ mlt_properties_set ( pnum , "readonly" , "no" );
+ }
+ }
+}
+
+void * load_lib( mlt_profile profile, mlt_service_type type , void* handle){
+
+ int i=0;
+ void (*f0r_get_plugin_info)(f0r_plugin_info_t*),
+ *f0r_construct , *f0r_update , *f0r_destruct,
+ (*f0r_get_param_info)(f0r_param_info_t* info, int param_index),
+ (*f0r_init)(void) , *f0r_deinit ,
+ (*f0r_set_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index),
+ (*f0r_get_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index),
+ (*f0r_update2) (f0r_instance_t instance, double time, const uint32_t* inframe1,
+ const uint32_t* inframe2,const uint32_t* inframe3, uint32_t* outframe);
+
+ if ( ( f0r_construct = dlsym(handle, "f0r_construct") ) &&
+ (f0r_update = dlsym(handle,"f0r_update") ) &&
+ (f0r_destruct = dlsym(handle,"f0r_destruct") ) &&
+ (f0r_get_plugin_info = dlsym(handle,"f0r_get_plugin_info") ) &&
+ (f0r_get_param_info = dlsym(handle,"f0r_get_param_info") ) &&
+ (f0r_set_param_value= dlsym(handle,"f0r_set_param_value" ) ) &&
+ (f0r_get_param_value= dlsym(handle,"f0r_get_param_value" ) ) &&
+ (f0r_init= dlsym(handle,"f0r_init" ) ) &&
+ (f0r_deinit= dlsym(handle,"f0r_deinit" ) )
+ ){
+
+ f0r_update2=dlsym(handle,"f0r_update2");
+
+ f0r_plugin_info_t info;
+ f0r_get_plugin_info(&info);
+
+ void* ret=NULL;
+ mlt_properties properties=NULL;
+
+ if (type == filter_type && info.plugin_type == F0R_PLUGIN_TYPE_FILTER ){
+ mlt_filter this = mlt_filter_new( );
+ if ( this != NULL )
+ {
+ this->process = filter_process;
+ this->close = filter_close;
+ f0r_init();
+ properties=MLT_FILTER_PROPERTIES ( this );
+
+ for (i=0;i<info.num_params;i++){
+ f0r_param_info_t pinfo;
+ f0r_get_param_info(&pinfo,i);
+
+ }
+
+ ret=this;
+ }
+ }else if (type == transition_type && info.plugin_type == F0R_PLUGIN_TYPE_MIXER2){
+ mlt_transition transition = mlt_transition_new( );
+ if ( transition != NULL )
+ {
+ transition->process = transition_process;
+ transition->close = transition_close;
+ properties=MLT_TRANSITION_PROPERTIES( transition );
+ mlt_properties_set_int(properties, "_transition_type", 1 );
+
+ ret=transition;
+ }
+ }
+ mlt_properties_set_data(properties, "_dlclose_handle", handle , sizeof (void*) , NULL , NULL );
+ mlt_properties_set_data(properties, "_dlclose", dlclose , sizeof (void*) , NULL , NULL );
+ mlt_properties_set_data(properties, "f0r_construct", f0r_construct , sizeof(void*),NULL,NULL);
+ mlt_properties_set_data(properties, "f0r_update", f0r_update , sizeof(void*),NULL,NULL);
+ if (f0r_update2)
+ mlt_properties_set_data(properties, "f0r_update2", f0r_update2 , sizeof(void*),NULL,NULL);
+ mlt_properties_set_data(properties, "f0r_destruct", f0r_destruct , sizeof(void*),NULL,NULL);
+ mlt_properties_set_data(properties, "f0r_get_plugin_info", f0r_get_plugin_info , sizeof(void*),NULL,NULL);
+ mlt_properties_set_data(properties, "f0r_get_param_info", f0r_get_param_info , sizeof(void*),NULL,NULL);
+ mlt_properties_set_data(properties, "f0r_set_param_value", f0r_set_param_value , sizeof(void*),NULL,NULL);
+ mlt_properties_set_data(properties, "f0r_get_param_value", f0r_get_param_value , sizeof(void*),NULL,NULL);
+
+
+ return ret;
+ }else{
+ printf("some was wrong\n");
+ dlerror();
+ }
+ return NULL;
+}
+
+void * create_frei0r_item ( mlt_profile profile, mlt_service_type type, const char *id, void *arg){
+
+ mlt_tokeniser tokeniser = mlt_tokeniser_init ( );
+ int dircount=mlt_tokeniser_parse_new (
+ tokeniser ,
+ getenv("MLT_FREI0R_PLUGIN_PATH") ? getenv("MLT_FREI0R_PLUGIN_PATH") : "/usr/lib/frei0r-1" ,
+ ":"
+ );
+ void* ret=NULL;
+ while (dircount--){
+ char soname[1024]="";
+
+ char *save_firstptr;
+ char *firstname=strtok_r(strdup(id),".",&save_firstptr);
+
+ firstname=strtok_r(NULL,".",&save_firstptr);
+ sprintf(soname,"%s/%s.so", mlt_tokeniser_get_string( tokeniser , dircount ) , firstname );
+
+ if (firstname){
+
+ void* handle=dlopen(soname,RTLD_LAZY);
+
+ if (handle ){
+ ret=load_lib ( profile , type , handle );
+ }else{
+ dlerror();
+ }
+ }
+ }
+ mlt_tokeniser_close ( tokeniser );
+ return ret;
+}
+
+
+MLT_REPOSITORY
+{
+ int i=0;
+ mlt_tokeniser tokeniser = mlt_tokeniser_init ( );
+ int dircount=mlt_tokeniser_parse_new (
+ tokeniser ,
+ getenv("MLT_FREI0R_PLUGIN_PATH") ? getenv("MLT_FREI0R_PLUGIN_PATH") : "/usr/lib/frei0r-1" ,
+ ":"
+ );
+
+ while (dircount--){
+
+ mlt_properties direntries = mlt_properties_new();
+ char* dirname = mlt_tokeniser_get_string ( tokeniser , dircount ) ;
+ mlt_properties_dir_list(direntries, dirname ,"*.so",1);
+
+ for (i=0;i<mlt_properties_count(direntries);i++){
+ char* name=mlt_properties_get_value(direntries,i);
+ char* shortname=name+strlen(dirname)+1;
+ char fname[1024]="";
+
+ strcat(fname,dirname);
+ strcat(fname,shortname);
+
+ char *save_firstptr;
+ char pluginname[1024]="frei0r.";
+ char* firstname = strtok_r ( shortname , "." , &save_firstptr );
+ strcat(pluginname,firstname);
+
+ void* handle=dlopen(strcat(name,".so"),RTLD_LAZY);
+ if (handle){
+ void (*plginfo)(f0r_plugin_info_t*)=dlsym(handle,"f0r_get_plugin_info");
+
+ if (plginfo){
+ f0r_plugin_info_t info;
+ plginfo(&info);
+
+ if (firstname && info.plugin_type==F0R_PLUGIN_TYPE_FILTER){
+ MLT_REGISTER( filter_type, pluginname, create_frei0r_item );
+ fill_param_info ( repository , handle, &info , filter_type , pluginname );
+ }
+ else if (firstname && info.plugin_type==F0R_PLUGIN_TYPE_MIXER2 ){
+ MLT_REGISTER( transition_type, pluginname, create_frei0r_item );
+ fill_param_info ( repository , handle, &info , transition_type , pluginname );
+ }
+ }
+ dlclose(handle);
+ }
+ }
+ mlt_properties_close(direntries);
+ }
+ mlt_tokeniser_close ( tokeniser );
+}
--- /dev/null
+/*
+ * filter_frei0r.c -- frei0r filter
+ * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
+ *
+ * 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 "frei0r_helper.h"
+#include <string.h>
+static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+
+ mlt_filter filter = mlt_frame_pop_service( this );
+ int error = mlt_frame_get_image( this, image, format, width, height, 1 );
+
+ if ( error == 0 && *image && *format == mlt_image_yuv422 )
+ {
+ mlt_position in = mlt_filter_get_in( filter );
+ mlt_position out = mlt_filter_get_out( filter );
+ mlt_position time = mlt_frame_get_position( this );
+ double position = ( double )( time - in ) / ( double )( out - in + 1 );
+
+ process_frei0r_item( filter_type , position, MLT_FILTER_PROPERTIES ( filter ), this , image, format , width , height , writable );
+
+ }
+
+ return error;
+}
+
+
+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;
+}
+
+void filter_close( mlt_filter this ){
+
+ destruct( MLT_FILTER_PROPERTIES ( this ) );
+
+}
--- /dev/null
+/*
+ * frei0r_helper.c -- frei0r helper
+ * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
+ *
+ * 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 "frei0r_helper.h"
+#include <frei0r.h>
+#include <string.h>
+
+ int process_frei0r_item( mlt_service_type type, double position , mlt_properties prop , mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){
+
+ int i=0;
+ f0r_instance_t ( *f0r_construct ) ( unsigned int , unsigned int ) = mlt_properties_get_data( prop , "f0r_construct" ,NULL);
+ void (*f0r_update)(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)=mlt_properties_get_data( prop , "f0r_update" ,NULL);
+ void (*f0r_destruct)(f0r_instance_t instance)=mlt_properties_get_data( prop , "f0r_destruct" ,NULL);
+
+ void (*f0r_get_plugin_info)(f0r_plugin_info_t*)=mlt_properties_get_data( prop, "f0r_get_plugin_info" ,NULL);
+ void (*f0r_get_param_info)(f0r_param_info_t* info, int param_index)=mlt_properties_get_data( prop , "f0r_get_param_info" ,NULL);
+ void (*f0r_set_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index)=mlt_properties_get_data( prop , "f0r_set_param_value" ,NULL);
+ void (*f0r_get_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index)=mlt_properties_get_data( prop , "f0r_get_param_value" ,NULL);
+ void (*f0r_update2) (f0r_instance_t instance, double time,
+ const uint32_t* inframe1,const uint32_t* inframe2,const uint32_t* inframe3,
+ uint32_t* outframe)=mlt_properties_get_data( prop , "f0r_update2" ,NULL);
+
+
+ //use as name the width and height
+ f0r_instance_t inst;
+ char ctorname[1024]="";
+ sprintf(ctorname,"ctor-%dx%d",*width,*height);
+
+ void* neu=mlt_properties_get_data( prop , ctorname ,NULL );
+ if (!f0r_construct){
+ //printf("no ctor\n");
+ return -1;
+ }
+ if ( neu == 0 ){
+ inst= f0r_construct(*width,*height);
+ mlt_properties_set_data( prop , ctorname , inst, sizeof(void*) , f0r_destruct , NULL );;
+ }else{
+ inst=mlt_properties_get_data( prop , ctorname , NULL );
+ }
+ if (f0r_get_plugin_info){
+ f0r_plugin_info_t info;
+ f0r_get_plugin_info(&info);
+ for (i=0;i<info.num_params;i++){
+ f0r_param_info_t pinfo;
+ f0r_get_param_info(&pinfo,i);
+ //set param if found
+ if (pinfo.type==F0R_PARAM_DOUBLE || pinfo.type==F0R_PARAM_BOOL){
+ double t=0.0;
+ f0r_get_param_value(inst,&t,i);
+
+ if (mlt_properties_get( prop , pinfo.name ) !=NULL ){
+ t=mlt_properties_get_double( prop , pinfo.name );
+ f0r_set_param_value(inst,&t,i);
+ }
+ }
+ }
+ }
+
+ int video_area = *width * *height;
+ uint32_t *img_a = mlt_pool_alloc( video_area * sizeof(uint32_t) );
+ uint32_t *img_b = mlt_pool_alloc( video_area * sizeof(uint32_t) );
+
+ if (type==filter_type){
+ mlt_convert_yuv422_to_rgb24a(*image, (uint8_t *)img_a, video_area);
+ f0r_update ( inst , position , img_a , img_b );
+ mlt_convert_rgb24a_to_yuv422((uint8_t *)img_b , *width, *height, *width * sizeof(uint32_t),
+ *image, NULL );
+ }else if (type==transition_type && f0r_update2 ){
+ uint32_t *result = mlt_pool_alloc( video_area * sizeof(uint32_t) );
+
+ mlt_convert_yuv422_to_rgb24a ( image[0] , (uint8_t *)img_a , video_area );
+ mlt_convert_yuv422_to_rgb24a ( image[1] , (uint8_t *)img_b , video_area );
+ uint8_t* yuv = mlt_pool_alloc( video_area * 3 );
+ f0r_update2 ( inst , position , img_a , img_b , NULL , result );
+ mlt_convert_rgb24a_to_yuv422((uint8_t *)result, *width, *height, *width * sizeof(uint32_t),
+ yuv, NULL );
+ image[2]=yuv;
+ }
+ mlt_pool_release(img_a);
+ mlt_pool_release(img_b);
+
+ return 0;
+}
+
+void destruct (mlt_properties prop ) {
+
+ void (*f0r_destruct)(f0r_instance_t instance)=mlt_properties_get_data( prop , "f0r_destruct" , NULL );
+ void (*f0r_deinit)(void)=mlt_properties_get_data ( prop , "f0r_deinit" , NULL);
+ int i=0;
+
+ if ( f0r_deinit != NULL )
+ f0r_deinit();
+
+ for ( i=0 ; i < mlt_properties_count ( prop ) ; i++ ){
+ if ( strstr ( mlt_properties_get_name ( prop , i ) , "ctor-" ) != NULL ){
+ void * inst=mlt_properties_get_data( prop , mlt_properties_get_name ( prop , i ) , NULL );
+ if ( inst != NULL ){
+ f0r_destruct( (f0r_instance_t) inst);
+ }
+ }
+ }
+ void (*dlclose)(void*)=mlt_properties_get_data ( prop , "_dlclose" , NULL);
+ void *handle=mlt_properties_get_data ( prop , "_dlclose_handle" , NULL);
+
+ if (handle && dlclose ){
+ dlclose ( handle );
+ }
+
+}
--- /dev/null
+/*
+ * frei0r_helper.h -- frei0r helper
+ * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
+ *
+ * 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>
+
+int process_frei0r_item( mlt_service_type type, double position , mlt_properties prop , mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable );
+void destruct (mlt_properties prop );
--- /dev/null
+/*
+ * transition_frei0r.c -- frei0r transition
+ * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
+ *
+ * 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 "frei0r_helper.h"
+#include <string.h>
+
+static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){
+
+ if (*format!=mlt_image_yuv422 ){
+ return -1;
+ }
+
+ mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
+ mlt_transition transition = mlt_frame_pop_service( a_frame );
+ mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
+ mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
+ mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
+
+ int invert = mlt_properties_get_int( properties, "invert" );
+
+ if ( mlt_properties_get( a_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( a_props, "rescale.interp" ), "none" ) )
+ mlt_properties_set( a_props, "rescale.interp", "nearest" );
+
+ // set consumer_aspect_ratio for a and b frame
+ if ( mlt_properties_get_double( a_props, "aspect_ratio" ) == 0.0 )
+ mlt_properties_set_double( a_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
+ if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 )
+ mlt_properties_set_double( b_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
+ mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
+
+
+ *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" );
+ *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" );
+
+ uint8_t *images[]={NULL,NULL,NULL};
+
+ mlt_frame_get_image( a_frame, &images[0], format, width, height, 1 );
+ mlt_frame_get_image( b_frame, &images[1], format, width, height, 1 );
+
+ mlt_position in = mlt_transition_get_in( transition );
+ mlt_position out = mlt_transition_get_out( transition );
+
+ // Get the position of the frame
+ char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" );
+ mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( a_frame ), name );
+
+ float pos=( float )( position - in ) / ( float )( out - in + 1 );
+
+ process_frei0r_item( transition_type , pos , properties, a_frame, images, format, width,height, writable );
+ if (images[2]){
+ *image=images[2];
+ }
+ return 0;
+}
+
+mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
+{
+ char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" );
+ mlt_properties_set_position( MLT_FRAME_PROPERTIES( a_frame ), name, mlt_frame_get_position( a_frame ) );
+ mlt_frame_push_service( a_frame, transition );
+ mlt_frame_push_frame( a_frame, b_frame );
+ mlt_frame_push_get_image( a_frame, transition_get_image );
+ return a_frame;
+}
+
+void transition_close( mlt_transition this ){
+ destruct ( MLT_TRANSITION_PROPERTIES ( this ) );
+}