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>
33 #define FILTER_NAME "vid.stab.detect"
35 typedef struct _stab_data
39 mlt_animation animation;
44 char* vectors_serializer(mlt_animation animation, int length)
46 return mlt_animation_serialize(animation);
50 char* lm_serializer(LocalMotions *lms, int length)
52 std::ostringstream oss;
53 int size = vs_vector_size(lms);
54 for (int i = 0; i < size; ++i)
56 LocalMotion* lm = (LocalMotion*) vs_vector_get(lms, i);
57 oss << lm->v.x << ' ';
58 oss << lm->v.y << ' ';
59 oss << lm->f.x << ' ';
60 oss << lm->f.y << ' ';
61 oss << lm->f.size << ' ';
62 oss << lm->contrast << ' ';
63 oss << lm->match << ' ';
65 return strdup(oss.str().c_str());
68 void lm_destructor(void *lms)
70 vs_vector_del(static_cast<VSVector*>(lms));
73 static void serialize_localmotions(StabData* data, LocalMotions &vectors, mlt_position pos)
75 mlt_animation_item_s item;
77 // Initialize animation item
79 item.frame = data->md.frameNum;
80 item.keyframe_type = mlt_keyframe_discrete;
81 item.property = mlt_property_init();
83 mlt_property_set_data(item.property, &vectors, 1, lm_destructor, (mlt_serialiser) lm_serializer);
84 mlt_animation_insert(data->animation, &item);
85 mlt_property_close(item.property);
88 int init_detect(StabData *data, mlt_properties properties, mlt_image_format *format, int *width, int *height)
90 VSPixelFormat pf = convertImageFormat(*format);
92 vsFrameInfoInit(&fi, *width, *height, pf);
94 VSMotionDetectConfig conf = vsMotionDetectGetDefaultConfig(FILTER_NAME);
95 conf.shakiness = mlt_properties_get_int(properties, "shakiness");
96 conf.accuracy = mlt_properties_get_int(properties, "accuracy");
97 conf.stepSize = mlt_properties_get_int(properties, "stepsize");
98 conf.algo = mlt_properties_get_int(properties, "algo");
99 conf.contrastThreshold = mlt_properties_get_double(properties, "mincontrast");
100 conf.show = mlt_properties_get_int(properties, "show");
101 conf.virtualTripod = mlt_properties_get_int(properties, "tripod");
103 vsMotionDetectInit(&data->md, &conf, &fi);
105 // change name of the filter, so the vid.stab.transform will be used in 2nd-pass.
106 mlt_properties_set(properties, "mlt_service", "vid.stab.transform");
110 static int get_image(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable)
112 mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
113 mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
115 *format = mlt_image_yuv420p;
116 StabData *data = static_cast<StabData*>(filter->child);
118 int error = mlt_frame_get_image(frame, image, format, width, height, writable);
121 // Service locks are for concurrency control
122 mlt_service_lock(MLT_FILTER_SERVICE(filter));
124 if (!data->initialized)
126 init_detect(data, properties, format, width, height);
127 data->initialized = true;
130 VSMotionDetect* md = &data->md;
131 LocalMotions localmotions;
133 vsFrameFillFromBuffer(&vsFrame, *image, &md->fi);
135 // detect and save motions
136 vsMotionDetection(md, &localmotions, &vsFrame);
137 mlt_position pos = mlt_filter_get_position( filter, frame );
138 serialize_localmotions(data, localmotions, pos);
140 mlt_service_unlock(MLT_FILTER_SERVICE(filter));
146 static mlt_frame process_filter(mlt_filter filter, mlt_frame frame)
148 mlt_frame_push_service(frame, filter);
149 mlt_frame_push_get_image(frame, get_image);
153 static void close_filter(mlt_filter filter)
155 StabData *data = static_cast<StabData*>(filter->child);
158 if (data->initialized)
160 vsMotionDetectionCleanup(&data->md);
163 filter->child = NULL;
170 mlt_filter filter_detect_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg)
172 mlt_filter filter = NULL;
174 StabData *data = new StabData;
175 memset(data, 0, sizeof(StabData));
177 if ((filter = mlt_filter_new()))
179 filter->process = process_filter;
180 filter->close = close_filter;
181 filter->child = data;
183 data->animation = mlt_animation_new();
184 data->parent = filter;
186 mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
187 mlt_properties_set(properties, "mlt_service", "vid.stab.transform");
189 //properties for stabilize
190 mlt_properties_set(properties, "shakiness", "4");
191 mlt_properties_set(properties, "accuracy", "4");
192 mlt_properties_set(properties, "stepsize", "6");
193 mlt_properties_set(properties, "algo", "1");
194 mlt_properties_set(properties, "mincontrast", "0.3");
195 mlt_properties_set(properties, "show", "0");
196 mlt_properties_set(properties, "tripod", "0");
198 // properties for transform
199 mlt_properties_set(properties, "smoothing", "10");
200 mlt_properties_set(properties, "maxshift", "-1");
201 mlt_properties_set(properties, "maxangle", "-1");
202 mlt_properties_set(properties, "crop", "0");
203 mlt_properties_set(properties, "invert", "0");
204 mlt_properties_set(properties, "relative", "1");
205 mlt_properties_set(properties, "zoom", "0");
206 mlt_properties_set(properties, "optzoom", "1");
207 mlt_properties_set(properties, "sharpen", "0.8");
209 mlt_properties_set(properties, "vid.stab.version", LIBVIDSTAB_VERSION);
210 mlt_properties_set_data(properties, "vectors", data->animation, 1, (mlt_destructor) mlt_animation_close,
211 (mlt_serialiser) vectors_serializer);