2 * filter_imagestab.c -- video stabilization with code from http://vstab.sourceforge.net/
3 * Copyright (c) 2011 Marco Gittler <g.marco@freenet.de>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <framework/mlt_filter.h>
21 #include <framework/mlt_frame.h>
22 #include <framework/mlt_log.h>
23 #include <framework/mlt_producer.h>
24 #include <framework/mlt_geometry.h>
32 #include "stabilize.h"
33 #include "transform_image.h"
36 static void serialize_vectors( StabData* self, mlt_position length )
38 mlt_geometry g = mlt_geometry_init();
42 struct mlt_geometry_item_s item;
45 // Initialize geometry item
46 item.key = item.f[0] = item.f[1] = 1;
47 item.f[2] = item.f[3] = item.f[4] = 1;
49 tlist* transform_data =self->transs;
50 for ( i = 0; i < length; i++ )
52 // Set the geometry item
55 if ( transform_data->data){
56 Transform* t=transform_data->data;
61 transform_data=transform_data->next;
64 // Add the geometry item
65 mlt_geometry_insert( g, &item );
68 // Put the analysis results in a property
69 mlt_geometry_set_length( g, length );
70 mlt_properties_set( MLT_FILTER_PROPERTIES( (mlt_filter) self->parent ), "vectors", mlt_geometry_serialise( g ) );
71 mlt_geometry_close( g );
75 Transform* deserialize_vectors( char *vectors, mlt_position length )
77 mlt_geometry g = mlt_geometry_init();
79 // Parse the property as a geometry
80 if ( !mlt_geometry_parse( g, vectors, length, -1, -1 ) )
82 struct mlt_geometry_item_s item;
84 tx=malloc(sizeof(Transform)*length);
85 memset(tx,sizeof(Transform)*length,0);
86 // Copy the geometry items to a vc array for interp()
87 for ( i = 0; i < length; i++ )
89 mlt_geometry_fetch( g, &item, i );
102 //mlt_log_warning( NULL, "failed to parse vectors\n" );
105 // We are done with this mlt_geometry
106 if ( g ) mlt_geometry_close( g );
110 static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
112 mlt_filter filter = mlt_frame_pop_service( frame );
113 //*format = mlt_image_rgb24;
114 *format = mlt_image_yuv420p;
115 int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
117 if ( !error && *image )
119 StabData* self = filter->child;
120 mlt_position length = mlt_filter_get_length2( filter, frame );
124 // Service locks are for concurrency control
125 mlt_service_lock( MLT_FILTER_SERVICE( filter ) );
126 if ( !self->initialized )
128 // Initialize our context
129 self->initialized = 1;
132 self->framesize=w*h* 3/2;//( mlt_image_format_size ( *format, w,h , 0) ; // 3/2 =1 too small
133 self->shakiness = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "shakiness" );
134 self->accuracy = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "accuracy" );
135 self->stepsize = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "stepsize" );
136 self->algo = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "algo" );
137 self->show = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "show" );
138 self->contrast_threshold = mlt_properties_get_double( MLT_FILTER_PROPERTIES(filter) , "mincontrast" );
139 stabilize_configure(self);
141 char *vectors = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "vectors" );
145 mlt_position pos = mlt_filter_get_position( filter, frame );
146 stabilize_filter_video ( self, *image, *format );
150 if ( pos == length - 1 )
152 serialize_vectors( self, length );
158 TransformData* tf=mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "_transformdata", NULL);
159 char *interps = mlt_properties_get( MLT_FRAME_PROPERTIES( frame ), "rescale.interp" );
162 tf=mlt_pool_alloc(sizeof(TransformData));
163 mlt_properties_set_data( MLT_FILTER_PROPERTIES(filter), "_transformdata", tf, 0, ( mlt_destructor )mlt_pool_release, NULL );
165 if ( self->initialized != 2 )
167 // Load analysis results from property
168 self->initialized = 2;
171 if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
173 else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
175 else if ( strcmp( interps, "bilinear" ) == 0 )
177 else if ( strcmp( interps, "bicubic" ) == 0 )
179 else if ( strcmp( interps, "bicublin" ) == 0 )
181 tf->interpoltype = interp;
182 transform_configure(tf,w,h,*format ,*image, deserialize_vectors( vectors, length ),length);
185 if ( self->initialized == 2 )
188 float pos = mlt_filter_get_position( filter, frame );
189 tf->current_trans=pos;
190 transform_filter_video(tf, *image, *format );
193 mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
198 static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
200 mlt_frame_push_service( frame, filter );
201 mlt_frame_push_get_image( frame, filter_get_image );
205 static void filter_close( mlt_filter parent )
207 StabData* self = parent->child;
208 stabilize_stop(self);
210 parent->close = NULL;
211 parent->child = NULL;
214 mlt_filter filter_videostab2_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
216 StabData* self = calloc( 1, sizeof(StabData) );
219 mlt_filter parent = mlt_filter_new();
220 parent->child = self;
221 parent->close = filter_close;
222 parent->process = filter_process;
223 self->parent = parent;
224 mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "shakiness", "4" );
225 mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "accuracy", "4" );
226 mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "stepsize", "6" );
227 mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "algo", "1" );
228 mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "mincontrast", "0.3" );
229 mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "show", "0" );