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 #define FILTER_NAME "vid.stab.deshake"
34 typedef struct _deshake_data
39 VSSlidingAvgTrans avg;
41 mlt_position lastFrame;
44 int init_deshake(DeshakeData *data, mlt_properties properties,
45 VSPixelFormat vs_format, int *width, int *height, char* interps)
47 VSFrameInfo fiIn, fiOut;
48 vsFrameInfoInit(&fiIn, *width, *height, vs_format);
49 vsFrameInfoInit(&fiOut, *width, *height, vs_format);
51 VSMotionDetectConfig conf = vsMotionDetectGetDefaultConfig(FILTER_NAME);
52 conf.shakiness = mlt_properties_get_int(properties, "shakiness");
53 conf.accuracy = mlt_properties_get_int(properties, "accuracy");
54 conf.stepSize = mlt_properties_get_int(properties, "stepsize");
55 conf.algo = mlt_properties_get_int(properties, "algo");
56 conf.contrastThreshold = mlt_properties_get_double(properties, "mincontrast");
59 vsMotionDetectInit(&data->md, &conf, &fiIn);
61 VSTransformConfig tdconf = vsTransformGetDefaultConfig(FILTER_NAME);
62 tdconf.smoothing = mlt_properties_get_int(properties, "smoothing");
63 tdconf.maxShift = mlt_properties_get_int(properties, "maxshift");
64 tdconf.maxAngle = mlt_properties_get_double(properties, "maxangle");
65 tdconf.crop = (VSBorderType) mlt_properties_get_int(properties, "crop");
66 tdconf.zoom = mlt_properties_get_int(properties, "zoom");
67 tdconf.optZoom = mlt_properties_get_int(properties, "optzoom");
68 tdconf.zoomSpeed = mlt_properties_get_double(properties, "zoomspeed");
72 // by default a bilinear interpolation is selected
73 tdconf.interpolType = VS_BiLinear;
74 if (strcmp(interps, "nearest") == 0 || strcmp(interps, "neighbor") == 0)
75 tdconf.interpolType = VS_Zero;
76 else if (strcmp(interps, "tiles") == 0 || strcmp(interps, "fast_bilinear") == 0)
77 tdconf.interpolType = VS_Linear;
79 vsTransformDataInit(&data->td, &tdconf, &fiIn, &fiOut);
81 data->avg.initialized = 0;
85 void clear_deshake(DeshakeData *data)
87 if (data->initialized)
89 vsMotionDetectionCleanup(&data->md);
90 vsTransformDataCleanup(&data->td);
94 static int get_image(mlt_frame frame, uint8_t **image, mlt_image_format *format,
95 int *width, int *height, int writable)
97 mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
98 mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
99 uint8_t* vs_image = NULL;
100 VSPixelFormat vs_format = PF_NONE;
102 // VS only works on progressive frames
103 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "consumer_deinterlace", 1 );
105 *format = validate_format( *format );
106 DeshakeData *data = static_cast<DeshakeData*>(filter->child);
108 int error = mlt_frame_get_image(frame, image, format, width, height, 1);
110 // Convert the received image to a format vid.stab can handle
113 vs_format = mltimage_to_vsimage( *format, *width, *height, *image, &vs_image );
118 // Service locks are for concurrency control
119 mlt_service_lock(MLT_FILTER_SERVICE(filter));
121 // Handle signal from app to re-init data
122 if (mlt_properties_get_int(properties, "refresh"))
124 mlt_properties_set(properties, "refresh", NULL);
126 data->initialized = false;
129 // clear deshake data, when seeking or dropping frames
130 mlt_position pos = mlt_filter_get_position(filter, frame);
131 if(pos != data->lastFrame+1) {
133 data->initialized = false;
135 data->lastFrame = pos;
137 if (!data->initialized)
139 char *interps = mlt_properties_get(MLT_FRAME_PROPERTIES(frame), "rescale.interp");
140 init_deshake(data, properties, vs_format, width, height,
142 data->initialized = true;
145 VSMotionDetect* md = &data->md;
146 VSTransformData* td = &data->td;
147 LocalMotions localmotions;
151 vsFrameFillFromBuffer(&vsFrame, vs_image, &md->fi);
152 vsMotionDetection(md, &localmotions, &vsFrame);
154 motion = vsSimpleMotionsToTransform(md->fi, FILTER_NAME, &localmotions);
155 vs_vector_del(&localmotions);
157 vsTransformPrepare(td, &vsFrame, &vsFrame);
159 VSTransform t = vsLowPassTransforms(td, &data->avg, &motion);
160 // mlt_log_warning(filter, "Trans: det: %f %f %f \n\t\t act: %f %f %f %f",
161 // motion.x, motion.y, motion.alpha,
162 // t.x, t.y, t.alpha, t.zoom);
163 vsDoTransform(td, t);
164 vsTransformFinish(td);
166 vsimage_to_mltimage( vs_image, *image, *format, *width, *height );
168 mlt_service_unlock(MLT_FILTER_SERVICE(filter));
170 free_vsimage( vs_image, vs_format );
176 static mlt_frame process_filter(mlt_filter filter, mlt_frame frame)
178 mlt_frame_push_service(frame, filter);
179 mlt_frame_push_get_image(frame, get_image);
183 static void close_filter(mlt_filter filter)
185 DeshakeData *data = static_cast<DeshakeData*>(filter->child);
190 filter->child = NULL;
197 mlt_filter filter_deshake_init(mlt_profile profile, mlt_service_type type,
198 const char *id, char *arg)
200 mlt_filter filter = NULL;
202 DeshakeData *data = new DeshakeData;
203 memset(data, 0, sizeof(DeshakeData));
205 if ((filter = mlt_filter_new()))
207 filter->process = process_filter;
208 filter->close = close_filter;
209 filter->child = data;
211 mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
212 //properties for stabilize
213 mlt_properties_set(properties, "shakiness", "4");
214 mlt_properties_set(properties, "accuracy", "4");
215 mlt_properties_set(properties, "stepsize", "6");
216 mlt_properties_set(properties, "algo", "1");
217 mlt_properties_set(properties, "mincontrast", "0.3");
219 //properties for transform
220 mlt_properties_set(properties, "smoothing", "15");
221 mlt_properties_set(properties, "maxshift", "-1");
222 mlt_properties_set(properties, "maxangle", "-1");
223 mlt_properties_set(properties, "crop", "0");
224 mlt_properties_set(properties, "zoom", "0");
225 mlt_properties_set(properties, "optzoom", "1");
226 mlt_properties_set(properties, "zoomspeed", "0.25");