]> git.sesse.net Git - mlt/commitdiff
Merge filter_detect and filter_transform into filter_vidstab
authorBrian Matherly <pez4brian@yahoo.com>
Sun, 12 Jan 2014 01:46:46 +0000 (19:46 -0600)
committerBrian Matherly <pez4brian@yahoo.com>
Sun, 12 Jan 2014 01:50:01 +0000 (19:50 -0600)
src/modules/vid.stab/Makefile
src/modules/vid.stab/common.h
src/modules/vid.stab/factory.c
src/modules/vid.stab/filter_detect.cpp [deleted file]
src/modules/vid.stab/filter_detect.yml [deleted file]
src/modules/vid.stab/filter_transform.cpp [deleted file]
src/modules/vid.stab/filter_transform.yml [deleted file]
src/modules/vid.stab/filter_vidstab.cpp
src/modules/vid.stab/filter_vidstab.yml

index b90cf75fcd9ac10a41882b5c830a121c2025a122..f9991b2319b5ca5ee45cb88ed169f2157f2ee7d5 100644 (file)
@@ -9,8 +9,6 @@ TARGET = ../libmltvidstab$(LIBSUF)
 OBJS = factory.o
 
 CPPOBJS = filter_deshake.o
-CPPOBJS += filter_detect.o
-CPPOBJS += filter_transform.o
 CPPOBJS += filter_vidstab.o
 
 CXXFLAGS += -Wno-deprecated $(CFLAGS)
index 96a2c9b013ec44ecc72eb43f56fc2beaaaaceb9e..b373dbdda56e9f107002b75a0541984c08190750 100644 (file)
@@ -26,7 +26,4 @@ inline VSPixelFormat convertImageFormat(mlt_image_format &format) {
        }
 }
 
-int get_image_and_detect(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable);
-int get_image_and_transform(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable);
-
 #endif /* VIDSTAB_COMMON_H_ */
index 25e5b430d0672941e158000c9c0b4701a3507776..ca416a5abb9ee68b521d1634c997b6ca5a89ae45 100644 (file)
@@ -22,8 +22,6 @@
 #include <framework/mlt.h>
 
 extern mlt_filter filter_deshake_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_detect_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_transform_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_filter filter_vidstab_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 
 static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
@@ -35,13 +33,9 @@ static mlt_properties metadata( mlt_service_type type, const char *id, void *dat
 
 MLT_REPOSITORY
 {
-       MLT_REGISTER( filter_type, "vid.stab.deshake", filter_deshake_init );
-       MLT_REGISTER( filter_type, "vid.stab.detect", filter_detect_init );
-       MLT_REGISTER( filter_type, "vid.stab.transform", filter_transform_init );
-       MLT_REGISTER( filter_type, "vid.stab", filter_vidstab_init );
+       MLT_REGISTER( filter_type, "deshake", filter_deshake_init );
+       MLT_REGISTER( filter_type, "vidstab", filter_vidstab_init );
        
-       MLT_REGISTER_METADATA( filter_type, "vid.stab.deshake", metadata, "filter_deshake.yml" );
-       MLT_REGISTER_METADATA( filter_type, "vid.stab.detect", metadata, "filter_detect.yml" );
-       MLT_REGISTER_METADATA( filter_type, "vid.stab.transform", metadata, "filter_transform.yml" );
-       MLT_REGISTER_METADATA( filter_type, "vid.stab", metadata, "filter_vidstab.yml" );
+       MLT_REGISTER_METADATA( filter_type, "deshake", metadata, "filter_deshake.yml" );
+       MLT_REGISTER_METADATA( filter_type, "vidstab", metadata, "filter_vidstab.yml" );
 }
diff --git a/src/modules/vid.stab/filter_detect.cpp b/src/modules/vid.stab/filter_detect.cpp
deleted file mode 100644 (file)
index a38f8bc..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * filter_detect.cpp
- * Copyright (C) 2013
- * Marco Gittler <g.marco@freenet.de>
- * Jakub Ksiezniak <j.ksiezniak@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-extern "C"
-{
-#include <vid.stab/libvidstab.h>
-#include <framework/mlt.h>
-#include <framework/mlt_animation.h>
-}
-
-#include <string.h>
-#include <assert.h>
-#include "common.h"
-
-typedef struct _stab_data
-{
-       VSMotionDetect md;
-       mlt_animation animation;
-} StabData;
-
-char* vectors_serializer(mlt_animation animation, int length)
-{
-       return mlt_animation_serialize(animation);
-}
-
-#include <sstream>
-char* lm_serializer(LocalMotions *lms, int length)
-{
-       std::ostringstream oss;
-       int size = vs_vector_size(lms);
-       for (int i = 0; i < size; ++i)
-       {
-               LocalMotion* lm = (LocalMotion*) vs_vector_get(lms, i);
-               oss << lm->v.x << ' ';
-               oss << lm->v.y << ' ';
-               oss << lm->f.x << ' ';
-               oss << lm->f.y << ' ';
-               oss << lm->f.size << ' ';
-               oss << lm->contrast << ' ';
-               oss << lm->match << ' ';
-       }
-       return strdup(oss.str().c_str());
-}
-
-void lm_destructor(void *lms)
-{
-       vs_vector_del(static_cast<VSVector*>(lms));
-}
-
-static void serialize_localmotions(StabData* data, LocalMotions &vectors, mlt_position pos)
-{
-       mlt_animation_item_s item;
-
-       // Initialize animation item
-       item.is_key = 1;
-       item.frame = data->md.frameNum;
-       item.keyframe_type = mlt_keyframe_discrete;
-       item.property = mlt_property_init();
-
-       mlt_property_set_data(item.property, &vectors, 1, lm_destructor, (mlt_serialiser) lm_serializer);
-       mlt_animation_insert(data->animation, &item);
-       mlt_property_close(item.property);
-}
-
-static StabData* init_detect(mlt_properties properties, mlt_image_format *format, int *width, int *height)
-{
-       StabData *data = new StabData;
-       memset(data, 0, sizeof(StabData));
-       data->animation = mlt_animation_new();
-
-       VSPixelFormat pf = convertImageFormat(*format);
-       VSFrameInfo fi;
-       vsFrameInfoInit(&fi, *width, *height, pf);
-
-       const char* filterName = mlt_properties_get(properties, "mlt_service");
-
-       VSMotionDetectConfig conf = vsMotionDetectGetDefaultConfig(filterName);
-       conf.shakiness = mlt_properties_get_int(properties, "shakiness");
-       conf.accuracy = mlt_properties_get_int(properties, "accuracy");
-       conf.stepSize = mlt_properties_get_int(properties, "stepsize");
-       conf.algo = mlt_properties_get_int(properties, "algo");
-       conf.contrastThreshold = mlt_properties_get_double(properties, "mincontrast");
-       conf.show = mlt_properties_get_int(properties, "show");
-       conf.virtualTripod = mlt_properties_get_int(properties, "tripod");
-       vsMotionDetectInit(&data->md, &conf, &fi);
-
-       // add vectors to properties
-       mlt_properties_set_data(properties, "vectors", data->animation, 1, (mlt_destructor) mlt_animation_close,
-                                       (mlt_serialiser) vectors_serializer);
-       return data;
-}
-
-void destroy_detect(StabData *data)
-{
-       if (data)
-       {
-               vsMotionDetectionCleanup(&data->md);
-               delete data;
-       }
-}
-
-int get_image_and_detect(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable)
-{
-       mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
-       mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
-
-       *format = mlt_image_yuv420p;
-
-       writable = writable || mlt_properties_get_int(properties, "show") ? 1 : 0;
-
-       int error = mlt_frame_get_image(frame, image, format, width, height, writable);
-       if (!error)
-       {
-               // Service locks are for concurrency control
-               mlt_service_lock(MLT_FILTER_SERVICE(filter));
-
-               StabData *data = static_cast<StabData*>(mlt_properties_get_data(properties, "_stab_data", NULL));
-               if (!data)
-               {
-                       data = init_detect(properties, format, width, height);
-                       mlt_properties_set_data(properties, "_stab_data", data, 0, (mlt_destructor) destroy_detect, NULL);
-               }
-
-               VSMotionDetect* md = &data->md;
-               LocalMotions localmotions;
-               VSFrame vsFrame;
-               vsFrameFillFromBuffer(&vsFrame, *image, &md->fi);
-
-               // detect and save motions
-               vsMotionDetection(md, &localmotions, &vsFrame);
-               mlt_position pos = mlt_filter_get_position( filter, frame );
-               serialize_localmotions(data, localmotions, pos);
-
-               mlt_service_unlock(MLT_FILTER_SERVICE(filter));
-       }
-
-       return error;
-}
-
-static mlt_frame process_filter(mlt_filter filter, mlt_frame frame)
-{
-       mlt_frame_push_service(frame, filter);
-       mlt_frame_push_get_image(frame, get_image_and_detect);
-       return frame;
-}
-
-extern "C"
-{
-
-mlt_filter filter_detect_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg)
-{
-       mlt_filter filter = NULL;
-
-       if ((filter = mlt_filter_new()))
-       {
-               filter->process = process_filter;
-
-               mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
-
-               //properties for stabilize
-               mlt_properties_set(properties, "shakiness", "4");
-               mlt_properties_set(properties, "accuracy", "4");
-               mlt_properties_set(properties, "stepsize", "6");
-               mlt_properties_set(properties, "algo", "1");
-               mlt_properties_set(properties, "mincontrast", "0.3");
-               mlt_properties_set(properties, "show", "0");
-               mlt_properties_set(properties, "tripod", "0");
-
-               // properties for transform
-               mlt_properties_set(properties, "smoothing", "15");
-               mlt_properties_set(properties, "maxshift", "-1");
-               mlt_properties_set(properties, "maxangle", "-1");
-               mlt_properties_set(properties, "crop", "0");
-               mlt_properties_set(properties, "invert", "0");
-               mlt_properties_set(properties, "relative", "1");
-               mlt_properties_set(properties, "zoom", "0");
-               mlt_properties_set(properties, "optzoom", "1");
-               mlt_properties_set(properties, "zoomspeed", "0.25");
-
-               mlt_properties_set(properties, "vid.stab.version", LIBVIDSTAB_VERSION);
-
-               return filter;
-       }
-
-       return NULL;
-}
-
-}
diff --git a/src/modules/vid.stab/filter_detect.yml b/src/modules/vid.stab/filter_detect.yml
deleted file mode 100644 (file)
index a02da16..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-schema_version: 0.1
-type: filter
-identifier: vid.stab.detect
-title: Vid.Stab Detect
-copyright: Jakub Ksiezniak
-creator: Marco Gittler <g.marco@freenet.de>
-version: 1
-license: GPL
-language: en
-url: http://public.hronopik.de/vid.stab/
-tags:
-  - Video
-description: Stabilize Video (for wiggly/rolling video)
-notes: >
-  This filter requires two passes. The first pass performs analysis and stores
-  the result in the vectors property. The second pass applies the vectors to
-  the image.
-  To use with melt, use 'melt ... -consumer xml:output.mlt all=1' for the
-  first pass. For the second pass, use output.mlt as the input.
-
-parameters:
-  - identifier: vectors (transform)
-    title: Vectors
-    type: geometry
-    description: >
-      A set of X/Y coordinates by which to adjust the image.
-      When this is not supplied, the filter computes the vectors and stores
-      them in this property when the last frame has been processed.
-
-  - identifier: shakiness
-    title: Shakiness
-    type: integer
-    description: How shaky is the video (analysis)
-    readonly: no
-    required: no
-    minimum: 1
-    maximum: 10
-    default: 4
-    mutable: yes
-    widget: spinner
-
-  - identifier: accuracy
-    title: Accuracy
-    type: integer
-    description: Accuracy of shakiness detection (analysis)
-    readonly: no
-    required: no
-    minimum: 1
-    maximum: 15
-    default: 4
-    mutable: yes
-    widget: spinner
-
-  - identifier: stepsize
-    title: Stepsize
-    type: integer
-    description: Step size of search process (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 100
-    default: 6
-    mutable: yes
-    widget: spinner
-
-  - identifier: algo
-    title: Algorithm
-    type: integer
-    description: 0 = brute force (translation only), 1 = small measurement fields (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 1
-    mutable: yes
-    widget: spinner
-
-  - identifier: mincontrast
-    title: Minimum Contrast
-    type: float
-    description: Below this contrast, a field is discarded (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0.3
-    mutable: yes
-    widget: spinner
-
-  - identifier: show
-    title: Show
-    type: integer
-    description: 0 = draw nothing, 1 or 2 = show fields and transforms (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 2
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: tripod
-    title: Tripod
-    type: integer
-    description: virtual tripod mode (if >0): motion is compared to a reference frame (frame N is the value)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 100000
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: smoothing
-    title: Smoothing
-    type: integer
-    description: number of frames for lowpass filtering (2N + 1 frames) (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 100
-    default: 15
-    mutable: yes
-    widget: spinner
-
-  - identifier: maxshift
-    title: Maxshift
-    type: integer
-    description: maximum translation, -1 = no limit (transform)
-    unit: pixels
-    readonly: no
-    required: no
-    minimum: -1
-    maximum: 1000
-    default: -1
-    mutable: yes
-    widget: spinner
-
-  - identifier: maxangle
-    title: Maxangle
-    type: float
-    description: max angle to rotate, -1 = no limit (transform)
-    unit: radians
-    readonly: no
-    required: no
-    minimum: -1
-    maximum: 3.142
-    default: -1
-    mutable: yes
-    widget: spinner
-
-  - identifier: crop
-    title: Crop
-    type: integer
-    description: 0 = keep border, 1 = black background (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: invert
-    title: Invert
-    type: integer
-    description: Invert transforms (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: relative
-    title: Relative Transform
-    type: integer
-    description: 0 = absolute, 1 = relative (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 1
-    mutable: yes
-    widget: spinner
-
-  - identifier: zoom
-    title: Zoom
-    type: integer
-    description: additional zoom amount (transform)
-    unit: percent
-    readonly: no
-    required: no
-    minimum: -500
-    maximum: 500
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: optzoom
-    title: Optimal Zoom
-    type: integer
-    description: automatically determine optimal zoom. 1 - static zoom, 2 - adaptive zoom (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 2
-    default: 1
-    mutable: yes
-    widget: spinner
-
-  - identifier: zoomspeed
-    title: Optimal Zoom Speed
-    type: float
-    description: zoom per frame in percent, (used when optzoom = 2) (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0.25
-    mutable: yes
-    widget: spinner
-
-  - identifier: refresh
-    description: >
-      Applications should set this when it updates a transform parameter.
-    type: integer
-    minimum: 0
-    maximum: 1
diff --git a/src/modules/vid.stab/filter_transform.cpp b/src/modules/vid.stab/filter_transform.cpp
deleted file mode 100644 (file)
index 66e3643..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * filter_transform.cpp
- * Copyright (C) 2013
- * Marco Gittler <g.marco@freenet.de>
- * Jakub Ksiezniak <j.ksiezniak@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-extern "C"
-{
-#include <vid.stab/libvidstab.h>
-#include <framework/mlt.h>
-#include <framework/mlt_animation.h>
-}
-
-#include <string.h>
-#include <assert.h>
-#include <sstream>
-#include "common.h"
-
-typedef struct
-{
-       VSTransformData td;
-       VSTransformations trans;
-} TransformData;
-
-int lm_deserialize(LocalMotions *lms, mlt_property property)
-{
-       std::istringstream iss(mlt_property_get_string(property));
-       vs_vector_init(lms, 0);
-
-       while (iss.good())
-       {
-               LocalMotion lm;
-               iss >> lm.v.x >> lm.v.y >> lm.f.x >> lm.f.y >> lm.f.size >> lm.contrast >> lm.match;
-               if (iss.fail())
-               {
-                       break;
-               }
-               vs_vector_append_dup(lms, &lm, sizeof(lm));
-       }
-       return 0;
-}
-
-int vectors_deserialize(mlt_animation anim, VSManyLocalMotions *mlms)
-{
-       int error = 0;
-       mlt_animation_item_s item;
-       item.property = mlt_property_init();
-
-       vs_vector_init(mlms, 1024); // initial number of frames, but it will be increased
-
-       int length = mlt_animation_get_length(anim);
-       for (int i = 0; i < length; ++i)
-       {
-               LocalMotions lms;
-
-               // read lms
-               mlt_animation_get_item(anim, &item, i + 1);
-               if ((error = lm_deserialize(&lms, item.property)))
-               {
-                       break;
-               }
-
-               vs_vector_set_dup(mlms, i, &lms, sizeof(LocalMotions));
-       }
-
-       mlt_property_close(item.property);
-       return error;
-}
-
-void destroy_transforms(TransformData *data)
-{
-       if (data)
-       {
-               vsTransformDataCleanup(&data->td);
-               vsTransformationsCleanup(&data->trans);
-               delete data;
-       }
-}
-
-TransformData* initialize_transforms(int *width, int *height, mlt_image_format *format,
-               mlt_properties properties, const char* interps)
-{
-       TransformData *data = new TransformData;
-       memset(data, 0, sizeof(TransformData));
-
-       VSPixelFormat pf = convertImageFormat(*format);
-       VSFrameInfo fi_src, fi_dst;
-       vsFrameInfoInit(&fi_src, *width, *height, pf);
-       vsFrameInfoInit(&fi_dst, *width, *height, pf);
-
-       const char* filterName = mlt_properties_get(properties, "mlt_service");
-
-       VSTransformConfig conf = vsTransformGetDefaultConfig(filterName);
-       conf.smoothing = mlt_properties_get_int(properties, "smoothing");
-       conf.maxShift = mlt_properties_get_int(properties, "maxshift");
-       conf.maxAngle = mlt_properties_get_double(properties, "maxangle");
-       conf.crop = (VSBorderType) mlt_properties_get_int(properties, "crop");
-       conf.zoom = mlt_properties_get_int(properties, "zoom");
-       conf.optZoom = mlt_properties_get_int(properties, "optzoom");
-       conf.zoomSpeed = mlt_properties_get_double(properties, "zoomspeed");
-       conf.relative = mlt_properties_get_int(properties, "relative");
-       conf.invert = mlt_properties_get_int(properties, "invert");
-       if (mlt_properties_get_int(properties, "tripod") != 0)
-       {
-               // Virtual tripod mode: relative=False, smoothing=0
-               conf.relative = 0;
-               conf.smoothing = 0;
-       }
-
-       // by default a bilinear interpolation is selected
-       conf.interpolType = VS_BiLinear;
-       if (strcmp(interps, "nearest") == 0 || strcmp(interps, "neighbor") == 0)
-               conf.interpolType = VS_Zero;
-       else if (strcmp(interps, "tiles") == 0 || strcmp(interps, "fast_bilinear") == 0)
-               conf.interpolType = VS_Linear;
-
-       vsTransformDataInit(&data->td, &conf, &fi_src, &fi_dst);
-       vsTransformationsInit(&data->trans);
-
-       // load transformations
-       mlt_animation animation = mlt_animation_new();
-       char* strAnim = mlt_properties_get(properties, "vectors");
-       if (mlt_animation_parse(animation, strAnim, 0, 0, NULL))
-       {
-               mlt_log_warning(NULL, "parse failed\n");
-               mlt_animation_close(animation);
-               destroy_transforms(data);
-               return NULL;
-       }
-
-       VSManyLocalMotions mlms;
-       if (vectors_deserialize(animation, &mlms))
-       {
-               mlt_animation_close(animation);
-               destroy_transforms(data);
-               return NULL;
-       }
-
-       mlt_animation_close(animation);
-
-       vsLocalmotions2Transforms(&data->td, &mlms, &data->trans);
-       vsPreprocessTransforms(&data->td, &data->trans);
-       return data;
-}
-
-int get_image_and_transform(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable)
-{
-       int error = 0;
-       mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
-       mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
-
-       *format = mlt_image_yuv420p;
-
-       error = mlt_frame_get_image(frame, image, format, width, height, 1);
-       if (!error)
-       {
-               // Service locks are for concurrency control
-               mlt_service_lock(MLT_FILTER_SERVICE(filter));
-
-               TransformData *data = static_cast<TransformData*>(mlt_properties_get_data(properties, "_transform_data", NULL));
-
-               // Handle signal from app to re-init data
-               if (mlt_properties_get_int(properties, "refresh"))
-               {
-                       mlt_properties_set(properties, "refresh", NULL);
-                       destroy_transforms(data);
-                       data = NULL;
-               }
-
-               if (!data)
-               {
-                       const char *interps = mlt_properties_get(MLT_FRAME_PROPERTIES(frame), "rescale.interp");
-                       data = initialize_transforms(width, height, format, properties, interps);
-                       if(!data) {
-                               mlt_service_unlock(MLT_FILTER_SERVICE(filter));
-                               return 1; // return error code
-                       }
-                       mlt_properties_set_data(properties, "_transform_data", data, 0, (mlt_destructor) destroy_transforms, NULL);
-               }
-
-               VSTransformData* td = &data->td;
-               VSFrame vsFrame;
-               vsFrameFillFromBuffer(&vsFrame, *image, vsTransformGetSrcFrameInfo(td));
-
-               // transform frame
-               data->trans.current = mlt_filter_get_position(filter, frame);
-               vsTransformPrepare(td, &vsFrame, &vsFrame);
-               VSTransform t = vsGetNextTransform(td, &data->trans);
-               vsDoTransform(td, t);
-               vsTransformFinish(td);
-
-               mlt_service_unlock(MLT_FILTER_SERVICE(filter));
-       }
-
-       return error;
-}
-
-static mlt_frame process_filter(mlt_filter filter, mlt_frame frame)
-{
-       mlt_frame_push_service(frame, filter);
-       mlt_frame_push_get_image(frame, get_image_and_transform);
-       return frame;
-}
-
-extern "C"
-{
-
-mlt_filter filter_transform_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg)
-{
-       mlt_filter filter = NULL;
-
-       if ((filter = mlt_filter_new()))
-       {
-               filter->process = process_filter;
-
-               mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
-
-               // properties for transform
-               mlt_properties_set(properties, "smoothing", "10");
-               mlt_properties_set(properties, "maxshift", "-1");
-               mlt_properties_set(properties, "maxangle", "-1");
-               mlt_properties_set(properties, "crop", "0");
-               mlt_properties_set(properties, "invert", "0");
-               mlt_properties_set(properties, "relative", "1");
-               mlt_properties_set(properties, "zoom", "0");
-               mlt_properties_set(properties, "optzoom", "1");
-               mlt_properties_set(properties, "zoomspeed", "0.25");
-
-               return filter;
-       }
-
-       return NULL;
-}
-
-}
diff --git a/src/modules/vid.stab/filter_transform.yml b/src/modules/vid.stab/filter_transform.yml
deleted file mode 100644 (file)
index 1e33c43..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-schema_version: 0.1
-type: filter
-identifier: videostab2
-title: Videostab2
-copyright: Copyright (C) 2011 Marco Gittler
-creator: Marco Gittler <g.marco@freenet.de>
-version: 0.1
-license: GPL
-language: en
-url: http://public.hronopik.de/vid.stab/
-tags:
-  - Video
-description: Stabilize Video (for wiggly/rolling video)
-notes: >
-  This filter requires two passes. The first pass performs analysis and stores
-  the result in the vectors property. The second pass applies the vectors to
-  the image.
-  To use with melt, use 'melt ... -consumer xml:output.mlt all=1' for the
-  first pass. For the second pass, use output.mlt as the input.
-
-parameters:
-  - identifier: vectors (transform)
-    title: Vectors
-    type: geometry
-    description: >
-      A set of X/Y coordinates by which to adjust the image.
-      When this is not supplied, the filter computes the vectors and stores
-      them in this property when the last frame has been processed.
-
-  - identifier: shakiness
-    title: Shakiness
-    type: integer
-    description: How shaky is the video (analysis)
-    readonly: no
-    required: no
-    minimum: 1
-    maximum: 10
-    default: 4
-    mutable: yes
-    widget: spinner
-
-  - identifier: accuracy
-    title: Accuracy
-    type: integer
-    description: Accuracy of shakiness detection (analysis)
-    readonly: no
-    required: no
-    minimum: 1
-    maximum: 15
-    default: 4
-    mutable: yes
-    widget: spinner
-
-  - identifier: stepsize
-    title: Stepsize
-    type: integer
-    description: Step size of search process (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 100
-    default: 6
-    mutable: yes
-    widget: spinner
-
-  - identifier: algo
-    title: Algorithm
-    type: integer
-    description: 0 = brute force (translation only), 1 = small measurement fields (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 1
-    mutable: yes
-    widget: spinner
-
-  - identifier: mincontrast
-    title: Minimum Contrast
-    type: float
-    description: Below this contrast, a field is discarded (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0.3
-    mutable: yes
-    widget: spinner
-
-  - identifier: show
-    title: Show
-    type: integer
-    description: 0 = draw nothing, 1 or 2 = show fields and transforms (analysis)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 2
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: smoothing
-    title: Smoothing
-    type: integer
-    description: number of frames for lowpass filtering (2N + 1 frames) (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 100
-    default: 15
-    mutable: yes
-    widget: spinner
-
-  - identifier: maxshift
-    title: Maxshift
-    type: integer
-    description: maximum translation, -1 = no limit (transform)
-    unit: pixels
-    readonly: no
-    required: no
-    minimum: -1
-    maximum: 1000
-    default: -1
-    mutable: yes
-    widget: spinner
-
-  - identifier: maxangle
-    title: Maxangle
-    type: float
-    description: max angle to rotate, -1 = no limit (transform)
-    unit: radians
-    readonly: no
-    required: no
-    minimum: -1
-    maximum: 3.142
-    default: -1
-    mutable: yes
-    widget: spinner
-
-  - identifier: crop
-    title: Crop
-    type: integer
-    description: 0 = keep border, 1 = black background (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: invert
-    title: Invert
-    type: integer
-    description: Invert transforms (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: relative
-    title: Relative Transform
-    type: integer
-    description: 0 = absolute, 1 = relative (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 1
-    mutable: yes
-    widget: spinner
-
-  - identifier: zoom
-    title: Zoom
-    type: integer
-    description: additional zoom amount (transform)
-    unit: percent
-    readonly: no
-    required: no
-    minimum: -500
-    maximum: 500
-    default: 0
-    mutable: yes
-    widget: spinner
-
-  - identifier: optzoom
-    title: Optimal Zoom
-    type: integer
-    description: automatically determine optimal zoom. 1 - static zoom, 2 - adaptive zoom (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 2
-    default: 1
-    mutable: yes
-    widget: spinner
-
-  - identifier: zoomspeed
-    title: Optimal Zoom Speed
-    type: float
-    description: zoom per frame in percent, (used when optzoom = 2) (transform)
-    readonly: no
-    required: no
-    minimum: 0
-    maximum: 1
-    default: 0.25
-    mutable: yes
-    widget: spinner
-
-  - identifier: refresh
-    description: >
-      Applications should set this when it updates a transform parameter.
-    type: integer
-    minimum: 0
-    maximum: 1
index ada37322ff7d8daaebfb0eb00563cc38a856c8e8..5bc44977fd384e4271c5f6a9294b2c6874a17b36 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * filter_deshake.cpp
+ * filter_vidstab.cpp
  * Copyright (C) 2013
  * Marco Gittler <g.marco@freenet.de>
  * Jakub Ksiezniak <j.ksiezniak@gmail.com>
@@ -23,12 +23,319 @@ extern "C"
 {
 #include <vid.stab/libvidstab.h>
 #include <framework/mlt.h>
+#include <framework/mlt_animation.h>
 }
 
+#include <sstream>
 #include <string.h>
 #include <assert.h>
 #include "common.h"
 
+
+typedef struct _stab_data
+{
+       VSMotionDetect md;
+       mlt_animation animation;
+} StabData;
+
+typedef struct
+{
+       VSTransformData td;
+       VSTransformations trans;
+} TransformData;
+
+
+char* vectors_serializer(mlt_animation animation, int length)
+{
+       return mlt_animation_serialize(animation);
+}
+
+char* lm_serializer(LocalMotions *lms, int length)
+{
+       std::ostringstream oss;
+       int size = vs_vector_size(lms);
+       for (int i = 0; i < size; ++i)
+       {
+               LocalMotion* lm = (LocalMotion*) vs_vector_get(lms, i);
+               oss << lm->v.x << ' ';
+               oss << lm->v.y << ' ';
+               oss << lm->f.x << ' ';
+               oss << lm->f.y << ' ';
+               oss << lm->f.size << ' ';
+               oss << lm->contrast << ' ';
+               oss << lm->match << ' ';
+       }
+       return strdup(oss.str().c_str());
+}
+
+int lm_deserialize(LocalMotions *lms, mlt_property property)
+{
+       std::istringstream iss(mlt_property_get_string(property));
+       vs_vector_init(lms, 0);
+
+       while (iss.good())
+       {
+               LocalMotion lm;
+               iss >> lm.v.x >> lm.v.y >> lm.f.x >> lm.f.y >> lm.f.size >> lm.contrast >> lm.match;
+               if (iss.fail())
+               {
+                       break;
+               }
+               vs_vector_append_dup(lms, &lm, sizeof(lm));
+       }
+       return 0;
+}
+
+void lm_destructor(void *lms)
+{
+       vs_vector_del(static_cast<VSVector*>(lms));
+}
+
+static void serialize_localmotions(StabData* data, LocalMotions &vectors, mlt_position pos)
+{
+       mlt_animation_item_s item;
+
+       // Initialize animation item
+       item.is_key = 1;
+       item.frame = data->md.frameNum;
+       item.keyframe_type = mlt_keyframe_discrete;
+       item.property = mlt_property_init();
+
+       mlt_property_set_data(item.property, &vectors, 1, lm_destructor, (mlt_serialiser) lm_serializer);
+       mlt_animation_insert(data->animation, &item);
+       mlt_property_close(item.property);
+}
+
+int vectors_deserialize(mlt_animation anim, VSManyLocalMotions *mlms)
+{
+       int error = 0;
+       mlt_animation_item_s item;
+       item.property = mlt_property_init();
+
+       vs_vector_init(mlms, 1024); // initial number of frames, but it will be increased
+
+       int length = mlt_animation_get_length(anim);
+       for (int i = 0; i < length; ++i)
+       {
+               LocalMotions lms;
+
+               // read lms
+               mlt_animation_get_item(anim, &item, i + 1);
+               if ((error = lm_deserialize(&lms, item.property)))
+               {
+                       break;
+               }
+
+               vs_vector_set_dup(mlms, i, &lms, sizeof(LocalMotions));
+       }
+
+       mlt_property_close(item.property);
+       return error;
+}
+
+void destroy_transforms(TransformData *data)
+{
+       if (data)
+       {
+               vsTransformDataCleanup(&data->td);
+               vsTransformationsCleanup(&data->trans);
+               delete data;
+       }
+}
+
+TransformData* initialize_transforms(int *width, int *height, mlt_image_format *format,
+               mlt_properties properties, const char* interps)
+{
+       TransformData *data = new TransformData;
+       memset(data, 0, sizeof(TransformData));
+
+       VSPixelFormat pf = convertImageFormat(*format);
+       VSFrameInfo fi_src, fi_dst;
+       vsFrameInfoInit(&fi_src, *width, *height, pf);
+       vsFrameInfoInit(&fi_dst, *width, *height, pf);
+
+       const char* filterName = mlt_properties_get(properties, "mlt_service");
+
+       VSTransformConfig conf = vsTransformGetDefaultConfig(filterName);
+       conf.smoothing = mlt_properties_get_int(properties, "smoothing");
+       conf.maxShift = mlt_properties_get_int(properties, "maxshift");
+       conf.maxAngle = mlt_properties_get_double(properties, "maxangle");
+       conf.crop = (VSBorderType) mlt_properties_get_int(properties, "crop");
+       conf.zoom = mlt_properties_get_int(properties, "zoom");
+       conf.optZoom = mlt_properties_get_int(properties, "optzoom");
+       conf.zoomSpeed = mlt_properties_get_double(properties, "zoomspeed");
+       conf.relative = mlt_properties_get_int(properties, "relative");
+       conf.invert = mlt_properties_get_int(properties, "invert");
+       if (mlt_properties_get_int(properties, "tripod") != 0)
+       {
+               // Virtual tripod mode: relative=False, smoothing=0
+               conf.relative = 0;
+               conf.smoothing = 0;
+       }
+
+       // by default a bilinear interpolation is selected
+       conf.interpolType = VS_BiLinear;
+       if (strcmp(interps, "nearest") == 0 || strcmp(interps, "neighbor") == 0)
+               conf.interpolType = VS_Zero;
+       else if (strcmp(interps, "tiles") == 0 || strcmp(interps, "fast_bilinear") == 0)
+               conf.interpolType = VS_Linear;
+
+       vsTransformDataInit(&data->td, &conf, &fi_src, &fi_dst);
+       vsTransformationsInit(&data->trans);
+
+       // load transformations
+       mlt_animation animation = mlt_animation_new();
+       char* strAnim = mlt_properties_get(properties, "vectors");
+       if (mlt_animation_parse(animation, strAnim, 0, 0, NULL))
+       {
+               mlt_log_warning(NULL, "parse failed\n");
+               mlt_animation_close(animation);
+               destroy_transforms(data);
+               return NULL;
+       }
+
+       VSManyLocalMotions mlms;
+       if (vectors_deserialize(animation, &mlms))
+       {
+               mlt_animation_close(animation);
+               destroy_transforms(data);
+               return NULL;
+       }
+
+       mlt_animation_close(animation);
+
+       vsLocalmotions2Transforms(&data->td, &mlms, &data->trans);
+       vsPreprocessTransforms(&data->td, &data->trans);
+       return data;
+}
+
+int get_image_and_transform(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable)
+{
+       int error = 0;
+       mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
+       mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
+
+       *format = mlt_image_yuv420p;
+
+       error = mlt_frame_get_image(frame, image, format, width, height, 1);
+       if (!error)
+       {
+               // Service locks are for concurrency control
+               mlt_service_lock(MLT_FILTER_SERVICE(filter));
+
+               TransformData *data = static_cast<TransformData*>(mlt_properties_get_data(properties, "_transform_data", NULL));
+
+               // Handle signal from app to re-init data
+               if (mlt_properties_get_int(properties, "refresh"))
+               {
+                       mlt_properties_set(properties, "refresh", NULL);
+                       destroy_transforms(data);
+                       data = NULL;
+               }
+
+               if (!data)
+               {
+                       const char *interps = mlt_properties_get(MLT_FRAME_PROPERTIES(frame), "rescale.interp");
+                       data = initialize_transforms(width, height, format, properties, interps);
+                       if(!data) {
+                               mlt_service_unlock(MLT_FILTER_SERVICE(filter));
+                               return 1; // return error code
+                       }
+                       mlt_properties_set_data(properties, "_transform_data", data, 0, (mlt_destructor) destroy_transforms, NULL);
+               }
+
+               VSTransformData* td = &data->td;
+               VSFrame vsFrame;
+               vsFrameFillFromBuffer(&vsFrame, *image, vsTransformGetSrcFrameInfo(td));
+
+               // transform frame
+               data->trans.current = mlt_filter_get_position(filter, frame);
+               vsTransformPrepare(td, &vsFrame, &vsFrame);
+               VSTransform t = vsGetNextTransform(td, &data->trans);
+               vsDoTransform(td, t);
+               vsTransformFinish(td);
+
+               mlt_service_unlock(MLT_FILTER_SERVICE(filter));
+       }
+
+       return error;
+}
+
+static StabData* init_detect(mlt_properties properties, mlt_image_format *format, int *width, int *height)
+{
+       StabData *data = new StabData;
+       memset(data, 0, sizeof(StabData));
+       data->animation = mlt_animation_new();
+
+       VSPixelFormat pf = convertImageFormat(*format);
+       VSFrameInfo fi;
+       vsFrameInfoInit(&fi, *width, *height, pf);
+
+       const char* filterName = mlt_properties_get(properties, "mlt_service");
+
+       VSMotionDetectConfig conf = vsMotionDetectGetDefaultConfig(filterName);
+       conf.shakiness = mlt_properties_get_int(properties, "shakiness");
+       conf.accuracy = mlt_properties_get_int(properties, "accuracy");
+       conf.stepSize = mlt_properties_get_int(properties, "stepsize");
+       conf.algo = mlt_properties_get_int(properties, "algo");
+       conf.contrastThreshold = mlt_properties_get_double(properties, "mincontrast");
+       conf.show = mlt_properties_get_int(properties, "show");
+       conf.virtualTripod = mlt_properties_get_int(properties, "tripod");
+       vsMotionDetectInit(&data->md, &conf, &fi);
+
+       // add vectors to properties
+       mlt_properties_set_data(properties, "vectors", data->animation, 1, (mlt_destructor) mlt_animation_close,
+                                       (mlt_serialiser) vectors_serializer);
+       return data;
+}
+
+void destroy_detect(StabData *data)
+{
+       if (data)
+       {
+               vsMotionDetectionCleanup(&data->md);
+               delete data;
+       }
+}
+
+int get_image_and_detect(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable)
+{
+       mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame);
+       mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
+
+       *format = mlt_image_yuv420p;
+
+       writable = writable || mlt_properties_get_int(properties, "show") ? 1 : 0;
+
+       int error = mlt_frame_get_image(frame, image, format, width, height, writable);
+       if (!error)
+       {
+               // Service locks are for concurrency control
+               mlt_service_lock(MLT_FILTER_SERVICE(filter));
+
+               StabData *data = static_cast<StabData*>(mlt_properties_get_data(properties, "_stab_data", NULL));
+               if (!data)
+               {
+                       data = init_detect(properties, format, width, height);
+                       mlt_properties_set_data(properties, "_stab_data", data, 0, (mlt_destructor) destroy_detect, NULL);
+               }
+
+               VSMotionDetect* md = &data->md;
+               LocalMotions localmotions;
+               VSFrame vsFrame;
+               vsFrameFillFromBuffer(&vsFrame, *image, &md->fi);
+
+               // detect and save motions
+               vsMotionDetection(md, &localmotions, &vsFrame);
+               mlt_position pos = mlt_filter_get_position( filter, frame );
+               serialize_localmotions(data, localmotions, pos);
+
+               mlt_service_unlock(MLT_FILTER_SERVICE(filter));
+       }
+
+       return error;
+}
+
 static mlt_frame process_filter(mlt_filter filter, mlt_frame frame)
 {
        mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
@@ -68,9 +375,9 @@ extern "C"
 mlt_filter filter_vidstab_init(mlt_profile profile, mlt_service_type type,
                const char *id, char *arg)
 {
-       mlt_filter filter = NULL;
+       mlt_filter filter = mlt_filter_new();
 
-       if ((filter = mlt_filter_new()))
+       if( filter )
        {
                filter->process = process_filter;
 
@@ -97,11 +404,9 @@ mlt_filter filter_vidstab_init(mlt_profile profile, mlt_service_type type,
                mlt_properties_set(properties, "zoomspeed", "0.25");
 
                mlt_properties_set(properties, "vid.stab.version", LIBVIDSTAB_VERSION);
-
-               return filter;
        }
 
-       return NULL;
+       return filter;
 }
 
 }
index b298cd3a1b5e0b8464c41b35c7597b89ec947299..c0f8c59149f12574e84a0395f4eec7c2d92f8b41 100644 (file)
@@ -1,6 +1,6 @@
 schema_version: 0.1
 type: filter
-identifier: vid.stab
+identifier: vidstab
 title: Vid.Stab Detect and Transform
 copyright: Jakub Ksiezniak
 creator: Marco Gittler <g.marco@freenet.de>