4 * Marco Gittler <g.marco@freenet.de>
5 * Jakub Ksiezniak <j.ksiezniak@gmail.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>
25 #include <framework/mlt.h>
26 #include <framework/mlt_animation.h>
37 VSTransformations trans;
40 int lm_deserialize(LocalMotions *lms, mlt_property property)
42 std::istringstream iss(mlt_property_get_string(property));
43 vs_vector_init(lms, 0);
48 iss >> lm.v.x >> lm.v.y >> lm.f.x >> lm.f.y >> lm.f.size >> lm.contrast >> lm.match;
53 vs_vector_append_dup(lms, &lm, sizeof(lm));
58 int vectors_deserialize(mlt_animation anim, VSManyLocalMotions *mlms)
61 mlt_animation_item_s item;
62 item.property = mlt_property_init();
64 vs_vector_init(mlms, 1024); // initial number of frames, but it will be increased
66 int length = mlt_animation_get_length(anim);
67 for (int i = 0; i < length; ++i)
72 mlt_animation_get_item(anim, &item, i + 1);
73 if ((error = lm_deserialize(&lms, item.property)))
78 vs_vector_set_dup(mlms, i, &lms, sizeof(LocalMotions));
81 mlt_property_close(item.property);
85 void destroy_transforms(TransformData *data)
89 vsTransformDataCleanup(&data->td);
90 vsTransformationsCleanup(&data->trans);
95 TransformData* initialize_transforms(int *width, int *height, mlt_image_format *format,
96 mlt_properties properties, const char* interps)
98 TransformData *data = new TransformData;
99 memset(data, 0, sizeof(TransformData));
101 VSPixelFormat pf = convertImageFormat(*format);
102 VSFrameInfo fi_src, fi_dst;
103 vsFrameInfoInit(&fi_src, *width, *height, pf);
104 vsFrameInfoInit(&fi_dst, *width, *height, pf);
106 const char* filterName = mlt_properties_get(properties, "mlt_service");
108 VSTransformConfig conf = vsTransformGetDefaultConfig(filterName);
109 conf.smoothing = mlt_properties_get_int(properties, "smoothing");
110 conf.maxShift = mlt_properties_get_int(properties, "maxshift");
111 conf.maxAngle = mlt_properties_get_double(properties, "maxangle");
112 conf.crop = (VSBorderType) mlt_properties_get_int(properties, "crop");
113 conf.zoom = mlt_properties_get_int(properties, "zoom");
114 conf.optZoom = mlt_properties_get_int(properties, "optzoom");
115 conf.zoomSpeed = mlt_properties_get_double(properties, "zoomspeed");
116 conf.relative = mlt_properties_get_int(properties, "relative");
117 conf.invert = mlt_properties_get_int(properties, "invert");
118 if (mlt_properties_get_int(properties, "tripod") != 0)
120 // Virtual tripod mode: relative=False, smoothing=0
125 // by default a bilinear interpolation is selected
126 conf.interpolType = VS_BiLinear;
127 if (strcmp(interps, "nearest") == 0 || strcmp(interps, "neighbor") == 0)
128 conf.interpolType = VS_Zero;
129 else if (strcmp(interps, "tiles") == 0 || strcmp(interps, "fast_bilinear") == 0)
130 conf.interpolType = VS_Linear;
132 vsTransformDataInit(&data->td, &conf, &fi_src, &fi_dst);
133 vsTransformationsInit(&data->trans);
135 // load transformations
136 mlt_animation animation = mlt_animation_new();
137 char* strAnim = mlt_properties_get(properties, "vectors");
138 if (mlt_animation_parse(animation, strAnim, 0, 0, NULL))
140 mlt_log_warning(NULL, "parse failed\n");
141 mlt_animation_close(animation);
142 destroy_transforms(data);
146 VSManyLocalMotions mlms;
147 if (vectors_deserialize(animation, &mlms))
149 mlt_animation_close(animation);
150 destroy_transforms(data);
154 mlt_animation_close(animation);
156 vsLocalmotions2Transforms(&data->td, &mlms, &data->trans);
157 vsPreprocessTransforms(&data->td, &data->trans);
161 int get_image_and_transform(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable)
164 mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
165 mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
167 *format = mlt_image_yuv420p;
169 error = mlt_frame_get_image(frame, image, format, width, height, 1);
172 // Service locks are for concurrency control
173 mlt_service_lock(MLT_FILTER_SERVICE(filter));
175 TransformData *data = static_cast<TransformData*>(mlt_properties_get_data(properties, "_transform_data", NULL));
177 // Handle signal from app to re-init data
178 if (mlt_properties_get_int(properties, "refresh"))
180 mlt_properties_set(properties, "refresh", NULL);
181 destroy_transforms(data);
187 const char *interps = mlt_properties_get(MLT_FRAME_PROPERTIES(frame), "rescale.interp");
188 data = initialize_transforms(width, height, format, properties, interps);
190 mlt_service_unlock(MLT_FILTER_SERVICE(filter));
191 return 1; // return error code
193 mlt_properties_set_data(properties, "_transform_data", data, 0, (mlt_destructor) destroy_transforms, NULL);
196 VSTransformData* td = &data->td;
198 vsFrameFillFromBuffer(&vsFrame, *image, vsTransformGetSrcFrameInfo(td));
201 data->trans.current = mlt_filter_get_position(filter, frame);
202 vsTransformPrepare(td, &vsFrame, &vsFrame);
203 VSTransform t = vsGetNextTransform(td, &data->trans);
204 vsDoTransform(td, t);
205 vsTransformFinish(td);
207 mlt_service_unlock(MLT_FILTER_SERVICE(filter));
213 static mlt_frame process_filter(mlt_filter filter, mlt_frame frame)
215 mlt_frame_push_service(frame, filter);
216 mlt_frame_push_get_image(frame, get_image_and_transform);
223 mlt_filter filter_transform_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg)
225 mlt_filter filter = NULL;
227 if ((filter = mlt_filter_new()))
229 filter->process = process_filter;
231 mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
233 // properties for transform
234 mlt_properties_set(properties, "smoothing", "10");
235 mlt_properties_set(properties, "maxshift", "-1");
236 mlt_properties_set(properties, "maxangle", "-1");
237 mlt_properties_set(properties, "crop", "0");
238 mlt_properties_set(properties, "invert", "0");
239 mlt_properties_set(properties, "relative", "1");
240 mlt_properties_set(properties, "zoom", "0");
241 mlt_properties_set(properties, "optzoom", "1");
242 mlt_properties_set(properties, "zoomspeed", "0.25");