3 * Copyright (C) 2013 Marco Gittler <g.marco@freenet.de>
4 * Copyright (C) 2013 Jakub Ksiezniak <j.ksiezniak@gmail.com>
5 * Copyright (C) 2014 Brian Matherly <pez4brian@yahoo.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <vid.stab/libvidstab.h>
28 #include <framework/mlt.h>
32 typedef struct _deshake_data
37 VSSlidingAvgTrans avg;
38 VSMotionDetectConfig mconf;
39 VSTransformConfig tconf;
40 mlt_position lastFrame;
43 static void get_config( VSTransformConfig* tconf, VSMotionDetectConfig* mconf, mlt_filter filter, mlt_frame frame )
45 mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
46 const char* filterName = mlt_properties_get( properties, "mlt_service" );
48 memset( mconf, 0, sizeof(VSMotionDetectConfig) );
49 *mconf = vsMotionDetectGetDefaultConfig( filterName );
50 mconf->shakiness = mlt_properties_get_int( properties, "shakiness" );
51 mconf->accuracy = mlt_properties_get_int(properties, "accuracy");
52 mconf->stepSize = mlt_properties_get_int(properties, "stepsize");
53 mconf->contrastThreshold = mlt_properties_get_double(properties, "mincontrast");
55 memset( tconf, 0, sizeof(VSTransformConfig) );
56 *tconf = vsTransformGetDefaultConfig( filterName );
57 tconf->smoothing = mlt_properties_get_int(properties, "smoothing");
58 tconf->maxShift = mlt_properties_get_int(properties, "maxshift");
59 tconf->maxAngle = mlt_properties_get_double(properties, "maxangle");
60 tconf->crop = (VSBorderType) mlt_properties_get_int(properties, "crop");
61 tconf->zoom = mlt_properties_get_int(properties, "zoom");
62 tconf->optZoom = mlt_properties_get_int(properties, "optzoom");
63 tconf->zoomSpeed = mlt_properties_get_double(properties, "zoomspeed");
66 // by default a bicubic interpolation is selected
67 const char *interps = mlt_properties_get( MLT_FRAME_PROPERTIES( frame ), "rescale.interp" );
68 tconf->interpolType = VS_BiCubic;
69 if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
70 tconf->interpolType = VS_Zero;
71 else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
72 tconf->interpolType = VS_Linear;
73 else if ( strcmp( interps, "bilinear" ) == 0 )
74 tconf->interpolType = VS_BiLinear;
77 static int check_config( mlt_filter filter, mlt_frame frame )
79 DeshakeData *data = static_cast<DeshakeData*>( filter->child );
80 VSTransformConfig new_tconf;
81 VSMotionDetectConfig new_mconf;
83 get_config( &new_tconf, &new_mconf, filter, frame );
85 if( compare_transform_config( &data->tconf, &new_tconf ) ||
86 compare_motion_config( &data->mconf, &new_mconf ) )
94 static void init_deshake( DeshakeData *data, mlt_filter filter, mlt_frame frame,
95 VSPixelFormat vs_format, int *width, int *height )
97 VSFrameInfo fiIn, fiOut;
99 vsFrameInfoInit( &fiIn, *width, *height, vs_format );
100 vsFrameInfoInit( &fiOut, *width, *height, vs_format );
101 get_config( &data->tconf, &data->mconf, filter, frame );
102 vsMotionDetectInit( &data->md, &data->mconf, &fiIn );
103 vsTransformDataInit(&data->td, &data->tconf, &fiIn, &fiOut);
105 data->avg.initialized = 0;
108 static void clear_deshake(DeshakeData *data)
110 if (data->initialized)
112 vsMotionDetectionCleanup(&data->md);
113 vsTransformDataCleanup(&data->td);
117 static int get_image(mlt_frame frame, uint8_t **image, mlt_image_format *format,
118 int *width, int *height, int writable)
120 mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
121 uint8_t* vs_image = NULL;
122 VSPixelFormat vs_format = PF_NONE;
124 // VS only works on progressive frames
125 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "consumer_deinterlace", 1 );
127 *format = validate_format( *format );
128 DeshakeData *data = static_cast<DeshakeData*>(filter->child);
130 int error = mlt_frame_get_image(frame, image, format, width, height, 1);
132 // Convert the received image to a format vid.stab can handle
135 vs_format = mltimage_to_vsimage( *format, *width, *height, *image, &vs_image );
140 // Service locks are for concurrency control
141 mlt_service_lock(MLT_FILTER_SERVICE(filter));
143 // clear deshake data, when seeking or dropping frames
144 mlt_position pos = mlt_filter_get_position( filter, frame );
145 if( pos != data->lastFrame + 1 ||
146 check_config( filter, frame) == 1 )
148 clear_deshake( data );
149 data->initialized = false;
151 data->lastFrame = pos;
153 if ( !data->initialized )
155 init_deshake( data, filter, frame, vs_format, width, height );
156 data->initialized = true;
159 VSMotionDetect* md = &data->md;
160 VSTransformData* td = &data->td;
161 LocalMotions localmotions;
165 vsFrameFillFromBuffer(&vsFrame, vs_image, &md->fi);
166 vsMotionDetection(md, &localmotions, &vsFrame);
168 const char* filterName = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "mlt_service" );
169 motion = vsSimpleMotionsToTransform(md->fi, filterName, &localmotions);
170 vs_vector_del(&localmotions);
172 vsTransformPrepare(td, &vsFrame, &vsFrame);
174 VSTransform t = vsLowPassTransforms(td, &data->avg, &motion);
175 // mlt_log_warning(filter, "Trans: det: %f %f %f \n\t\t act: %f %f %f %f",
176 // motion.x, motion.y, motion.alpha,
177 // t.x, t.y, t.alpha, t.zoom);
178 vsDoTransform(td, t);
179 vsTransformFinish(td);
181 vsimage_to_mltimage( vs_image, *image, *format, *width, *height );
183 mlt_service_unlock(MLT_FILTER_SERVICE(filter));
185 free_vsimage( vs_image, vs_format );
191 static mlt_frame process_filter(mlt_filter filter, mlt_frame frame)
193 mlt_frame_push_service(frame, filter);
194 mlt_frame_push_get_image(frame, get_image);
198 static void close_filter(mlt_filter filter)
200 DeshakeData *data = static_cast<DeshakeData*>(filter->child);
205 filter->child = NULL;
212 mlt_filter filter_deshake_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
214 mlt_filter filter = NULL;
216 DeshakeData *data = new DeshakeData;
217 memset(data, 0, sizeof(DeshakeData));
219 if ((filter = mlt_filter_new()))
221 filter->process = process_filter;
222 filter->close = close_filter;
223 filter->child = data;
225 mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
226 //properties for stabilize
227 mlt_properties_set(properties, "shakiness", "4");
228 mlt_properties_set(properties, "accuracy", "4");
229 mlt_properties_set(properties, "stepsize", "6");
230 mlt_properties_set(properties, "mincontrast", "0.3");
232 //properties for transform
233 mlt_properties_set(properties, "smoothing", "15");
234 mlt_properties_set(properties, "maxshift", "-1");
235 mlt_properties_set(properties, "maxangle", "-1");
236 mlt_properties_set(properties, "crop", "0");
237 mlt_properties_set(properties, "zoom", "0");
238 mlt_properties_set(properties, "optzoom", "1");
239 mlt_properties_set(properties, "zoomspeed", "0.25");