Imported Debian version 1.0~trusty
[deb_vid.stab.git] / transcode / filter_stabilize.c
CommitLineData
80f575fc
DM
1/*
2 * filter_stabilize.c
3 *
4 * Copyright (C) Georg Martius - June 2007
5 * georg dot martius at web dot de
6 *
7 * This file is part of transcode, a video stream processing tool
8 *
9 * transcode is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * transcode is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Make; see the file COPYING. If not, write to
21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25/* Typical call:
26 * transcode -V -J stabilize=shakiness=5:show=1,preview
27 * -i inp.mpeg -y null,null -o dummy
28 * all parameters are optional
29 */
30
31#include "libvidstab.h"
32
33#define MOD_NAME "filter_stabilize.so"
34#define MOD_VERSION LIBVIDSTAB_VERSION
35#define MOD_CAP "extracts relative transformations of \n\
36 subsequent frames (used for stabilization together with the\n\
37 transform filter in a second pass)"
38#define MOD_AUTHOR "Georg Martius"
39
40/* Ideas:
41 - Try OpenCL/Cuda, this should work great
42 - use smoothing on the frames and then use gradient decent!
43 - stepsize could be adapted (maybe to check only one field with large
44 stepsize and use the maximally required for the other fields
45*/
46
47#define MOD_FEATURES \
48 TC_MODULE_FEATURE_FILTER|TC_MODULE_FEATURE_VIDEO
49#define MOD_FLAGS \
50 TC_MODULE_FLAG_RECONFIGURABLE | TC_MODULE_FLAG_DELAY
51
52
53#define DEFAULT_TRANS_FILE_NAME "transforms.dat"
54
55#include <math.h>
56#include <libgen.h>
57
58#include "transcode.h"
59#include "filter.h"
60#include "libtc/libtc.h"
61#include "libtc/optstr.h"
62#include "libtc/tccodecs.h"
63#include "libtc/tcmodule-plugin.h"
64
65#include "transcode_specifics.h"
66
67/* private date structure of this filter*/
68typedef struct _stab_data {
69 VSMotionDetect md;
70 vob_t* vob; // pointer to information structure
71
72 char* result;
73 FILE* f;
74
75 char conf_str[TC_BUF_MIN];
76} StabData;
77
78/*************************************************************************/
79
80/* Module interface routines and data. */
81
82/*************************************************************************/
83
84/**
85 * stabilize_init: Initialize this instance of the module. See
86 * tcmodule-data.h for function details.
87 */
88
89static int stabilize_init(TCModuleInstance *self, uint32_t features)
90{
91 StabData* sd = NULL;
92 TC_MODULE_SELF_CHECK(self, "init");
93 TC_MODULE_INIT_CHECK(self, MOD_FEATURES, features);
94
95 setLogFunctions();
96
97 sd = tc_zalloc(sizeof(StabData)); // allocation with zero values
98 if (!sd) {
99 if (verbose > TC_INFO)
100 tc_log_error(MOD_NAME, "init: out of memory!");
101 return TC_ERROR;
102 }
103
104 sd->vob = tc_get_vob();
105 if (!sd->vob)
106 return TC_ERROR;
107
108 /**** Initialise private data structure */
109
110 self->userdata = sd;
111 if (verbose & TC_INFO){
112 tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);
113 }
114
115 return TC_OK;
116}
117
118
119/*
120 * stabilize_fini: Clean up after this instance of the module. See
121 * tcmodule-data.h for function details.
122 */
123static int stabilize_fini(TCModuleInstance *self)
124{
125 StabData *sd = NULL;
126 TC_MODULE_SELF_CHECK(self, "fini");
127 sd = self->userdata;
128
129 tc_free(sd);
130 self->userdata = NULL;
131 return TC_OK;
132}
133
134/*
135 * stabilize_configure: Configure this instance of the module. See
136 * tcmodule-data.h for function details.
137 */
138static int stabilize_configure(TCModuleInstance *self,
139 const char *options, vob_t *vob)
140{
141 StabData *sd = NULL;
142 TC_MODULE_SELF_CHECK(self, "configure");
143 char* filenamecopy, *filebasename;
144
145 sd = self->userdata;
146
147 /* sd->framesize = sd->vob->im_v_width * MAX_PLANES *
148 sizeof(char) * 2 * sd->vob->im_v_height * 2; */
149
150 VSMotionDetect* md = &(sd->md);
151 VSFrameInfo fi;
152 vsFrameInfoInit(&fi, sd->vob->ex_v_width, sd->vob->ex_v_height,
153 transcode2ourPF(vob->im_v_codec));
154
155 VSMotionDetectConfig conf = vsMotionDetectGetDefaultConfig(MOD_NAME);
156
157 sd->result = tc_malloc(TC_BUF_LINE);
158 filenamecopy = tc_strdup(sd->vob->video_in_file);
159 filebasename = basename(filenamecopy);
160 if (strlen(filebasename) < TC_BUF_LINE - 4) {
161 tc_snprintf(sd->result, TC_BUF_LINE, "%s.trf", filebasename);
162 } else {
163 tc_log_warn(MOD_NAME, "input name too long, using default `%s'",
164 DEFAULT_TRANS_FILE_NAME);
165 tc_snprintf(sd->result, TC_BUF_LINE, DEFAULT_TRANS_FILE_NAME);
166 }
167
168 if (options != NULL) {
169 // for some reason this plugin is called in the old fashion
170 // (not with inspect). Anyway we support both ways of getting help.
171 if(optstr_lookup(options, "help")) {
172 tc_log_info(MOD_NAME,vs_motiondetect_help);
173 return(TC_IMPORT_ERROR);
174 }
175
176 optstr_get(options, "result", "%[^:]", sd->result);
177 optstr_get(options, "shakiness", "%d", &conf.shakiness);
178 optstr_get(options, "accuracy", "%d", &conf.accuracy);
179 optstr_get(options, "stepsize", "%d", &conf.stepSize);
180 optstr_get(options, "algo", "%d", &conf.algo);
181 optstr_get(options, "mincontrast","%lf",&conf.contrastThreshold);
182 optstr_get(options, "tripod", "%d", &conf.virtualTripod);
183 optstr_get(options, "show", "%d", &conf.show);
184 }
185
186 if(vsMotionDetectInit(md, &conf, &fi) != VS_OK){
187 tc_log_error(MOD_NAME, "initialization of Motion Detection failed");
188 return TC_ERROR;
189 }
190 vsMotionDetectGetConfig(&conf,md);
191
192 if (verbose) {
193 tc_log_info(MOD_NAME, "Image Stabilization Settings:");
194 tc_log_info(MOD_NAME, " shakiness = %d", conf.shakiness);
195 tc_log_info(MOD_NAME, " accuracy = %d", conf.accuracy);
196 tc_log_info(MOD_NAME, " stepsize = %d", conf.stepSize);
197 tc_log_info(MOD_NAME, " algo = %d", conf.algo);
198 tc_log_info(MOD_NAME, " mincontrast = %f", conf.contrastThreshold);
199 tc_log_info(MOD_NAME, " tripod = %d", conf.virtualTripod);
200 tc_log_info(MOD_NAME, " show = %d", conf.show);
201 tc_log_info(MOD_NAME, " result = %s", sd->result);
202 }
203
204 sd->f = fopen(sd->result, "w");
205 if (sd->f == NULL) {
206 tc_log_error(MOD_NAME, "cannot open result file %s!\n", sd->result);
207 return TC_ERROR;
208 }else{
209 if(vsPrepareFile(md, sd->f) != VS_OK){
210 tc_log_error(MOD_NAME, "cannot write to result file %s", sd->result);
211 return TC_ERROR;
212 }
213 }
214
215 return TC_OK;
216}
217
218
219/**
220 * stabilize_filter_video: performs the analysis of subsequent frames
221 * See tcmodule-data.h for function details.
222 */
223
224static int stabilize_filter_video(TCModuleInstance *self,
225 vframe_list_t *frame)
226{
227 StabData *sd = NULL;
228
229 TC_MODULE_SELF_CHECK(self, "filter_video");
230 TC_MODULE_SELF_CHECK(frame, "filter_video");
231
232 sd = self->userdata;
233 VSMotionDetect* md = &(sd->md);
234 LocalMotions localmotions;
235 VSFrame vsFrame;
236 vsFrameFillFromBuffer(&vsFrame,frame->video_buf, &md->fi);
237
238 if(vsMotionDetection(md, &localmotions, &vsFrame)!= VS_OK){
239 tc_log_error(MOD_NAME, "motion detection failed");
240 return TC_ERROR;
241 }
242 if(vsWriteToFile(md, sd->f, &localmotions) != VS_OK){
243 vs_vector_del(&localmotions);
244 return TC_ERROR;
245 } else {
246 vs_vector_del(&localmotions);
247 return TC_OK;
248 }
249}
250
251/**
252 * stabilize_stop: Reset this instance of the module. See tcmodule-data.h
253 * for function details.
254 */
255
256static int stabilize_stop(TCModuleInstance *self)
257{
258 StabData *sd = NULL;
259 TC_MODULE_SELF_CHECK(self, "stop");
260 sd = self->userdata;
261 VSMotionDetect* md = &(sd->md);
262 if (sd->f) {
263 fclose(sd->f);
264 sd->f = NULL;
265 }
266
267 vsMotionDetectionCleanup(md);
268 if (sd->result) {
269 tc_free(sd->result);
270 sd->result = NULL;
271 }
272 return TC_OK;
273}
274
275/* checks for parameter in function _inspect */
276#define CHECKPARAM(paramname, formatstring, variable) \
277 if (optstr_lookup(param, paramname)) { \
278 tc_snprintf(sd->conf_str, sizeof(sd->conf_str), \
279 formatstring, variable); \
280 *value = sd->conf_str; \
281 }
282
283/**
284 * stabilize_inspect: Return the value of an option in this instance of
285 * the module. See tcmodule-data.h for function details.
286 */
287
288static int stabilize_inspect(TCModuleInstance *self,
289 const char *param, const char **value)
290{
291 StabData *sd = NULL;
292
293 TC_MODULE_SELF_CHECK(self, "inspect");
294 TC_MODULE_SELF_CHECK(param, "inspect");
295 TC_MODULE_SELF_CHECK(value, "inspect");
296 sd = self->userdata;
297 VSMotionDetect* md = &(sd->md);
298 if (optstr_lookup(param, "help")) {
299 *value = vs_motiondetect_help;
300 }
301 VSMotionDetectConfig conf;
302 vsMotionDetectGetConfig(&conf,md);
303
304 CHECKPARAM("shakiness","shakiness=%d", conf.shakiness);
305 CHECKPARAM("accuracy", "accuracy=%d", conf.accuracy);
306 CHECKPARAM("stepsize", "stepsize=%d", conf.stepSize);
307 CHECKPARAM("algo", "algo=%d", conf.algo);
308 CHECKPARAM("tripod", "tripod=%d", conf.virtualTripod);
309 CHECKPARAM("show", "show=%d", conf.show);
310 CHECKPARAM("result", "result=%s", sd->result);
311 return TC_OK;
312}
313
314static const TCCodecID stabilize_codecs_in[] = {
315 TC_CODEC_YUV420P, TC_CODEC_YUV422P, TC_CODEC_RGB, TC_CODEC_ERROR
316};
317static const TCCodecID stabilize_codecs_out[] = {
318 TC_CODEC_YUV420P, TC_CODEC_YUV422P, TC_CODEC_RGB, TC_CODEC_ERROR
319};
320TC_MODULE_FILTER_FORMATS(stabilize);
321
322TC_MODULE_INFO(stabilize);
323
324static const TCModuleClass stabilize_class = {
325 TC_MODULE_CLASS_HEAD(stabilize),
326
327 .init = stabilize_init,
328 .fini = stabilize_fini,
329 .configure = stabilize_configure,
330 .stop = stabilize_stop,
331 .inspect = stabilize_inspect,
332
333 .filter_video = stabilize_filter_video,
334};
335
336TC_MODULE_ENTRY_POINT(stabilize)
337
338/*************************************************************************/
339
340static int stabilize_get_config(TCModuleInstance *self, char *options)
341{
342 TC_MODULE_SELF_CHECK(self, "get_config");
343
344 optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION,
345 MOD_AUTHOR, "VRY4", "1");
346
347 return TC_OK;
348}
349
350static int stabilize_process(TCModuleInstance *self, frame_list_t *frame)
351{
352 TC_MODULE_SELF_CHECK(self, "process");
353
354// if (frame->tag & TC_PRE_S_PROCESS && frame->tag & TC_VIDEO) {
355 if (frame->tag & TC_POST_S_PROCESS && frame->tag & TC_VIDEO) {
356 return stabilize_filter_video(self, (vframe_list_t *)frame);
357 }
358 return TC_OK;
359}
360
361/*************************************************************************/
362
363TC_FILTER_OLDINTERFACE(stabilize)
364
365/*************************************************************************/
366
367/*
368 * Local variables:
369 * c-file-style: "stroustrup"
370 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
371 * indent-tabs-mode: nil
372 * c-basic-offset: 2 t
373 * End:
374 *
375 * vim: expandtab shiftwidth=2:
376 */