[packages/vid.stab] - new, with update from git
qboosh
qboosh at pld-linux.org
Tue Jul 16 16:22:42 CEST 2013
commit ca14007dbc5cc183b5dbeaa0abe448178f6b3234
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date: Tue Jul 16 16:22:31 2013 +0200
- new, with update from git
vid.stab-git.patch | 8669 ++++++++++++++++++++++++++++++++++++++++++++++++++++
vid.stab.spec | 72 +
2 files changed, 8741 insertions(+)
---
diff --git a/vid.stab.spec b/vid.stab.spec
new file mode 100644
index 0000000..60d2a43
--- /dev/null
+++ b/vid.stab.spec
@@ -0,0 +1,72 @@
+#
+# Conditional build:
+%bcond_with sse2 # use SSE2 instructions
+#
+%ifarch pentium4 %{x8664}
+%define with_sse2 1
+%endif
+Summary: Vid.Stab - video stabilization library
+Summary(pl.UTF-8): Vid.Stab - biblioteka do stabilizacji obrazu
+Name: vid.stab
+Version: 0.96
+Release: 1
+License: GPL v2+
+Group: Libraries
+#Source0Download: http://public.hronopik.de/vid.stab/download.php
+Source0: https://github.com/georgmartius/vid.stab/tarball/release-%{version}?/%{name}-%{version}.tar.gz
+# Source0-md5: 3dda75371b71e0e695cb1f679691c23c
+Patch0: %{name}-git.patch
+URL: http://public.hronopik.de/vid.stab/
+BuildRequires: cmake >= 2.6
+BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%description
+Vid.Stab is a library for stabilizing video clips.
+
+%description -l pl.UTF-8
+Vid.Stab to biblioteka do stabilizacji filmów.
+
+%package devel
+Summary: Header files for vid.stab library
+Summary(pl.UTF-8): Pliki nagłówkowe biblioteki vid.stab
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Header files for vid.stab library.
+
+%description devel -l pl.UTF-8
+Pliki nagłówkowe biblioteki vid.stab.
+
+%prep
+%setup -q -n georgmartius-%{name}-254ee37
+%patch0 -p1
+
+%build
+cd src
+%cmake . \
+ %{!?with_sse:-DSSE2_FOUND=OFF}
+%{__make}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+%{__make} -C src install \
+ DESTDIR=$RPM_BUILD_ROOT
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(644,root,root,755)
+%doc Changelog LICENSE README Todo
+%attr(755,root,root) %{_libdir}/libvidstab.so.0.9
+
+%files devel
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_libdir}/libvidstab.so
+%{_includedir}/vid.stab
+%{_pkgconfigdir}/vidstab.pc
diff --git a/vid.stab-git.patch b/vid.stab-git.patch
new file mode 100644
index 0000000..4bc7801
--- /dev/null
+++ b/vid.stab-git.patch
@@ -0,0 +1,8669 @@
+diff --git a/CMakeModules/FindSSE.cmake b/CMakeModules/FindSSE.cmake
+new file mode 100644
+index 0000000..6ece876
+--- /dev/null
++++ b/CMakeModules/FindSSE.cmake
+@@ -0,0 +1,104 @@
++# Check if SSE instructions are available on the machine where
++# the project is compiled.
++
++IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
++ EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO)
++
++ STRING(REGEX REPLACE "^.*(sse2).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "sse2" "${SSE_THERE}" SSE2_TRUE)
++ IF (SSE2_TRUE)
++ set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
++ ELSE (SSE2_TRUE)
++ set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
++ ENDIF (SSE2_TRUE)
++
++ # /proc/cpuinfo apparently omits sse3 :(
++ STRING(REGEX REPLACE "^.*[^s](sse3).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "sse3" "${SSE_THERE}" SSE3_TRUE)
++ IF (NOT SSE3_TRUE)
++ STRING(REGEX REPLACE "^.*(T2300).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "T2300" "${SSE_THERE}" SSE3_TRUE)
++ ENDIF (NOT SSE3_TRUE)
++
++ STRING(REGEX REPLACE "^.*(ssse3).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "ssse3" "${SSE_THERE}" SSSE3_TRUE)
++ IF (SSE3_TRUE OR SSSE3_TRUE)
++ set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
++ ELSE (SSE3_TRUE OR SSSE3_TRUE)
++ set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
++ ENDIF (SSE3_TRUE OR SSSE3_TRUE)
++ IF (SSSE3_TRUE)
++ set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
++ ELSE (SSSE3_TRUE)
++ set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
++ ENDIF (SSSE3_TRUE)
++
++ STRING(REGEX REPLACE "^.*(sse4_1).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE)
++ IF (SSE41_TRUE)
++ set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
++ ELSE (SSE41_TRUE)
++ set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
++ ENDIF (SSE41_TRUE)
++ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
++ EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE
++ CPUINFO)
++
++ STRING(REGEX REPLACE "^.*[^S](SSE2).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE)
++ IF (SSE2_TRUE)
++ set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
++ ELSE (SSE2_TRUE)
++ set(SSE2_FOUND false CACHE BOOL "SSE2 available on host")
++ ENDIF (SSE2_TRUE)
++
++ STRING(REGEX REPLACE "^.*[^S](SSE3).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "SSE3" "${SSE_THERE}" SSE3_TRUE)
++ IF (SSE3_TRUE)
++ set(SSE3_FOUND true CACHE BOOL "SSE3 available on host")
++ ELSE (SSE3_TRUE)
++ set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
++ ENDIF (SSE3_TRUE)
++
++ STRING(REGEX REPLACE "^.*(SSSE3).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "SSSE3" "${SSE_THERE}" SSSE3_TRUE)
++ IF (SSSE3_TRUE)
++ set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host")
++ ELSE (SSSE3_TRUE)
++ set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
++ ENDIF (SSSE3_TRUE)
++
++ STRING(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO})
++ STRING(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE)
++ IF (SSE41_TRUE)
++ set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host")
++ ELSE (SSE41_TRUE)
++ set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
++ ENDIF (SSE41_TRUE)
++ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows")
++ # TODO
++ set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
++ set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
++ set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
++ set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
++ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux")
++ set(SSE2_FOUND true CACHE BOOL "SSE2 available on host")
++ set(SSE3_FOUND false CACHE BOOL "SSE3 available on host")
++ set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host")
++ set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host")
++ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
++
++if(NOT SSE2_FOUND)
++ MESSAGE(STATUS "Could not find hardware support for SSE2 on this machine.")
++endif(NOT SSE2_FOUND)
++if(NOT SSE3_FOUND)
++ MESSAGE(STATUS "Could not find hardware support for SSE3 on this machine.")
++endif(NOT SSE3_FOUND)
++if(NOT SSSE3_FOUND)
++ MESSAGE(STATUS "Could not find hardware support for SSSE3 on this machine.")
++endif(NOT SSSE3_FOUND)
++if(NOT SSE4_1_FOUND)
++ MESSAGE(STATUS "Could not find hardware support for SSE4.1 on this machine.")
++endif(NOT SSE4_1_FOUND)
++
++mark_as_advanced(SSE2_FOUND SSE3_FOUND SSSE3_FOUND SSE4_1_FOUND)
+diff --git a/CMakeModules/WritePgkConfig.cmake b/CMakeModules/WritePgkConfig.cmake
+new file mode 100644
+index 0000000..caf9499
+--- /dev/null
++++ b/CMakeModules/WritePgkConfig.cmake
+@@ -0,0 +1,25 @@
++#
++# Write a pkg-config pc file for given "name" with "decription"
++# Arguments:
++# name: a library name (without "lib" prefix and "so" suffixes
++# desc: a desription string
++#
++macro (create_pkgconfig_file name desc)
++ set(_pkgfname "${CMAKE_CURRENT_BINARY_DIR}/${name}.pc")
++ message(STATUS "${name}: writing pkgconfig file ${_pkgfname}")
++
++ file(WRITE "${_pkgfname}" "# file generated by razor-qt cmake build
++prefix=${CMAKE_INSTALL_PREFIX}
++libdir=\${prefix}/lib${LIB_SUFFIX}
++includedir=\${prefix}/include
++
++Name: ${name}
++Description: ${desc}
++Version: ${VIDSTAB_VERSION}
++Libs: -L\${libdir} -l${name}
++Cflags: -I\${includedir}
++
++")
++
++ install(FILES ${_pkgfname} DESTINATION lib${LIB_SUFFIX}/pkgconfig)
++endmacro()
+\ No newline at end of file
+diff --git a/CMakeModules/create_pkgconfig_file.cmake b/CMakeModules/create_pkgconfig_file.cmake
+new file mode 100644
+index 0000000..c941f09
+--- /dev/null
++++ b/CMakeModules/create_pkgconfig_file.cmake
+@@ -0,0 +1,25 @@
++#
++# Write a pkg-config pc file for given "name" with "decription"
++# Arguments:
++# name: a library name (without "lib" prefix and "so" suffixes
++# desc: a desription string
++#
++macro (create_pkgconfig_file name desc)
++ set(_pkgfname "${CMAKE_CURRENT_BINARY_DIR}/${name}.pc")
++ message(STATUS "${name}: writing pkgconfig file ${_pkgfname}")
++
++ file(WRITE "${_pkgfname}" "# file generated by vid.stab cmake build
++prefix=${CMAKE_INSTALL_PREFIX}
++libdir=\${prefix}/lib${LIB_SUFFIX}
++includedir=\${prefix}/include
++
++Name: ${name}
++Description: ${desc}
++Version: ${VIDSTAB_VERSION}
++Libs: -L\${libdir} -l${name}
++Cflags: -I\${includedir}
++
++")
++
++ install(FILES ${_pkgfname} DESTINATION lib/pkgconfig)
++endmacro()
+\ No newline at end of file
+diff --git a/Install b/Install
+new file mode 100644
+index 0000000..15d5eee
+--- /dev/null
++++ b/Install
+@@ -0,0 +1,31 @@
++*** LIBRARY ***
++To compile the library do:
++
++cd src/cmake
++
++cmake ../
++make
++sudo make install
++
++To customize the installation prefix use
++cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local
++
++
++*** TRANSCODE plugins ***
++
++You need to have the transcode sources installed. The best
++choice it to download the same version you have in your distribution.
++Youi don't need to compile transcode itself.
++Download from http://tcforge.berlios.de/ or
++ http://developer.berlios.de/project/showfiles.php?group_id=10094.
++Then you need to adapt the transcode/CMakeLists.txt and change
++ the variable
++> set(TRANSCODE_ROOT path/to/transcode)
++
++cd transcode/cmake
++make
++. install.sh
++
++*** FFMPEG ***
++
++You need to configure ffmpeg with --enable-vidstab
+\ No newline at end of file
+diff --git a/README b/README
+index 467c5f3..c688a84 100644
+--- a/README
++++ b/README
+@@ -1,3 +1,5 @@
++Video stabilization library with plugins for transcode and ffmpeg.
++
+ See Install
+
+ please visit
+diff --git a/Todo b/Todo
+index 073dbdc..f386dd9 100644
+--- a/Todo
++++ b/Todo
+@@ -6,7 +6,3 @@ Some things that could be done
+
+ - make transform stage work with fifo file for transforms, such that streaming is also possible with 2-stage version.
+
+-- write full motion detection to file and delegate final transformation detection to snd-phase
+-
+-
+-- frei0r plugin
+\ No newline at end of file
+diff --git a/libavfilter/README b/libavfilter/README
+index 9dad132..fef17db 100644
+--- a/libavfilter/README
++++ b/libavfilter/README
+@@ -1,35 +1,7 @@
+-These are filters for the libavfilter framework.
+-
+-Hopefully they get integrated into ffmpeg but until then you have
+- to do the following to get it working:
+-link the files to your
+-ffmpeg/libavfilter/
+-
+-also link the vid.stab source directory
+-ln -s ...../vid.stab/src ffmpeg/libavfilter/
+-
+-(for now, to find the include files
+-later we have to make an own lib with header files and so on)
+-
+-add the following lines to the files in libavfilter/
+-allfilters.c
+-
+- REGISTER_FILTER (STABILIZE, stabilize, vf);
+- REGISTER_FILTER (TRANSFORM, transform, vf);
+-
+-Makefile
+-
+-to OBJS = .... optstr.o
+-
+-and further down
+-OBJS-$(CONFIG_STABILIZE_FILTER) += vf_stabilize.o
+-OBJS-$(CONFIG_TRANSFORM_FILTER) += vf_transform.o
+-
+-and
+-configure ffmpeg with
+-
+---extra-libs="-L/path/to/vidstab/src/cmake -lvidstab"
++These files are now in the ffmpeg source tree (as of 25.04.2013). They will be removed here at some point.
+
++Make sure you configure ffmpeg with
++--enable-vidstab
+
+
+
+diff --git a/libavfilter/git-workflow.txt b/libavfilter/git-workflow.txt
+new file mode 100644
+index 0000000..4d786f5
+--- /dev/null
++++ b/libavfilter/git-workflow.txt
+@@ -0,0 +1,20 @@
++
++#How to work in the ffmpeg git (or in any other one actually)
++#Create a new branch
++git branch "BRANCHNAME"
++git checkout "BRANCHNAME"
++#do you stuff
++git commit
++#rebase to master such that your changes only against the master branch and can be squashed
++git rebase -i master
++#or if merged in between then
++git log
++# or to find original branch point:
++diff -u <(git rev-list --first-parent BRANCHNAME) <(git rev-list --first-parent master) | sed -ne 's/^ //p' | head -1
++
++git rebase -i 39423.....
++
++git format-patch -s 3969b4b861ce8152e3195e8f8c3437abd2..
++
++
++007989c7a2215f54aeaf2393ab3aff0c208e862f
+diff --git a/libavfilter/optstr.c b/libavfilter/optstr.c
+deleted file mode 100644
+index ddd4439..0000000
+--- a/libavfilter/optstr.c
++++ /dev/null
+@@ -1,145 +0,0 @@
+-/*
+- * optstr.c
+- *
+- * This is a shortened version of the optstr.c file from transcode
+- * Copyright (C) Tilmann Bitterberg 2003
+- *
+- * Description: A general purpose option string parser
+- *
+- * Usage: see optstr.h, please
+- *
+- * This file is part of transcode, a video stream processing tool
+- *
+- * transcode 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, or (at your option)
+- * any later version.
+- *
+- * transcode 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 GNU Make; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-#ifdef HAVE_CONFIG_H
+-# include "config.h"
+-#endif
+-
+-/* for vsscanf */
+-#ifdef HAVE_VSSCANF
+-# define _GNU_SOURCE
+-#endif
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <stdarg.h>
+-#include "optstr.h"
+-
+-
+-// take from transcode
+-const char* optstr_lookup(const char *haystack, const char *needle)
+-{
+- const char *ch = haystack;
+- int found = 0;
+- size_t len = strlen(needle);
+-
+- while (!found) {
+- ch = strstr(ch, needle);
+-
+- /* not in string */
+- if (!ch) {
+- break;
+- }
+-
+- /* do we want this hit? ie is it exact? */
+- if (ch[len] == '\0' || ch[len] == '=' || ch[len] == ARG_SEP) {
+- found = 1;
+- } else {
+- /* go a little further */
+- ch++;
+- }
+- }
+-
+- return ch;
+-}
+-
+-int optstr_get(const char *options, const char *name, const char *fmt, ...)
+-{
+- va_list ap; /* points to each unnamed arg in turn */
+- int num_args = 0, n = 0;
+- size_t pos, fmt_len = strlen(fmt);
+- const char *ch = NULL;
+-
+-#ifndef HAVE_VSSCANF
+- void *temp[ARG_MAXIMUM];
+-#endif
+-
+- ch = optstr_lookup(options, name);
+- if (!ch) {
+- return -1;
+- }
+-
+- /* name IS in options */
+-
+- /* Find how many arguments we expect */
+- for (pos = 0; pos < fmt_len; pos++) {
+- if (fmt[pos] == '%') {
+- ++num_args;
+- /* is this one quoted with '%%' */
+- if (pos + 1 < fmt_len && fmt[pos + 1] == '%') {
+- --num_args;
+- ++pos;
+- }
+- }
+- }
+-
+-#ifndef HAVE_VSSCANF
+- if (num_args > ARG_MAXIMUM) {
+- fprintf (stderr,
+- "(%s:%d) Internal Overflow; redefine ARG_MAXIMUM (%d) to something higher\n",
+- __FILE__, __LINE__, ARG_MAXIMUM);
+- return -2;
+- }
+-#endif
+-
+- n = num_args;
+- /* Bool argument */
+- if (num_args <= 0) {
+- return 0;
+- }
+-
+- /* skip the `=' (if it is one) */
+- ch += strlen( name );
+- if( *ch == '=' )
+- ch++;
+-
+- if( !*ch )
+- return 0;
+-
+- va_start(ap, fmt);
+-
+-#ifndef HAVE_VSSCANF
+- while (--n >= 0) {
+- temp[num_args - n - 1] = va_arg(ap, void *);
+- }
+-
+- n = sscanf(ch, fmt,
+- temp[0], temp[1], temp[2], temp[3]);
+-
+-#else
+- /* this would be very nice instead of the above,
+- * but it does not seem portable
+- */
+- n = vsscanf(ch, fmt, ap);
+-#endif
+-
+- va_end(ap);
+-
+- return n;
+-}
+diff --git a/libavfilter/optstr.h b/libavfilter/optstr.h
+deleted file mode 100644
+index 64cb483..0000000
+--- a/libavfilter/optstr.h
++++ /dev/null
+@@ -1,57 +0,0 @@
+-#ifndef OPTSTR_H
+-#define OPTSTR_H
+-
+-#define ARG_MAXIMUM (4)
+-#define ARG_SEP ':'
+-#define ARG_CONFIG_LEN 8192
+-
+-/*
+- * optstr_lookup:
+- * Finds the _exact_ 'needle' in 'haystack' (naming intentionally
+- * identical to the 'strstr' (3) linux man page)
+- *
+- * Parameters:
+- * needle: substring to be searched
+- * haystack: string which is supposed to contain the substring
+- * Return Value:
+- * constant pointer to first substring found, or NULL if substring
+- * isn't found.
+- * Side effects:
+- * none
+- * Preconditions:
+- * none
+- * Postconditions:
+- * none
+- */
+-const char * optstr_lookup(const char *haystack, const char *needle);
+-
+-/*
+- * optstr_get:
+- * extract values from option string
+- *
+- * Parameters:
+- * options: a null terminated string of options to parse,
+- * syntax is "opt1=val1:opt_bool:opt2=val1-val2"
+- * where ':' is the seperator.
+- * name: the name to look for in options; eg "opt2"
+- * fmt: the format to scan values (printf format); eg "%d-%d"
+- * (...): variables to assign; eg &lower, &upper
+- * Return value:
+- * -2 internal error
+- * -1 `name' is not in `options'
+- * 0 `name' is in `options'
+- * >0 number of arguments assigned
+- * Side effects:
+- * none
+- * Preconditions:
+- * none
+- * Postconditions:
+- * none
+- */
+-int optstr_get(const char *options, const char *name, const char *fmt, ...)
+-#ifdef HAVE_GCC_ATTRIBUTES
+-__attribute__((format(scanf,3,4)))
+-#endif
+-;
+-
+-#endif /* OPTSTR_H */
+diff --git a/libavfilter/vf_stabilize.c b/libavfilter/vf_stabilize.c
+deleted file mode 100644
+index 6596d8d..0000000
+--- a/libavfilter/vf_stabilize.c
++++ /dev/null
+@@ -1,328 +0,0 @@
+-/*
+- * vf_stabilize.c
+- *
+- * Copyright (C) Georg Martius - Jan 2012
+- * georg dot martius at web dot de
+- *
+- * This file is part of vid.stab, video deshaking lib
+- *
+- * vid.stab 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, or (at your option)
+- * any later version.
+- *
+- * vid.stab 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 GNU Make; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-/* Typical call:
+- * ffmpeg -i input -vf stabilize=shakiness=5:show=1 dummy.avi
+- * all parameters are optional
+- */
+-
+-
+-/*
+- TODO: check AVERROR codes
+-*/
+-
+-#define DEFAULT_TRANS_FILE_NAME "transforms.dat"
+-#define VS_INPUT_MAXLEN 1024
+-
+-#include <math.h> //?
+-#include <libgen.h> //?
+-
+-#include "libavutil/avstring.h"
+-#include "libavutil/common.h"
+-#include "libavutil/mem.h"
+-#include "libavutil/pixdesc.h"
+-#include "libavutil/pixfmt.h"
+-#include "libavutil/imgutils.h"
+-#include "libavcodec/dsputil.h"
+-#include "avfilter.h"
+-#include "formats.h"
+-#include "internal.h"
+-#include "video.h"
+-
+-
+-#include "optstr.h"
+-#include "vid.stab/libvidstab.h"
+-
+-/* private date structure of this filter*/
+-typedef struct _stab_data {
+- AVClass av_class;
+-
+- MotionDetect md;
+- AVFilterBufferRef *ref; ///< Previous frame
+- char* options;
+-
+- char* result;
+- FILE* f;
+-
+-} StabData;
+-
+-static PixelFormat AV2OurPixelFormat(AVFilterContext *ctx, enum AVPixelFormat pf){
+- switch(pf){
+- case AV_PIX_FMT_YUV420P: return PF_YUV420P;
+- case AV_PIX_FMT_YUV422P: return PF_YUV422P;
+- case AV_PIX_FMT_YUV444P: return PF_YUV444P;
+- case AV_PIX_FMT_YUV410P: return PF_YUV410P;
+- case AV_PIX_FMT_YUV411P: return PF_YUV411P;
+- case AV_PIX_FMT_YUV440P: return PF_YUV440P;
+- case AV_PIX_FMT_YUVA420P: return PF_YUVA420P;
+- case AV_PIX_FMT_GRAY8: return PF_GRAY8;
+- case AV_PIX_FMT_RGB24: return PF_RGB24;
+- case AV_PIX_FMT_BGR24: return PF_BGR24;
+- case AV_PIX_FMT_RGBA: return PF_RGBA;
+- default:
+- av_log(ctx, AV_LOG_ERROR, "cannot deal with pixel format %i!\n", pf);
+- return PF_NONE;
+- }
+-}
+-
+-
+-/*************************************************************************/
+-
+-/* Module interface routines and data. */
+-
+-/*************************************************************************/
+-
+-static av_cold int init(AVFilterContext *ctx, const char *args)
+-{
+-
+- StabData* sd = ctx->priv;
+-
+- if (!sd) {
+- av_log(ctx, AV_LOG_INFO, "init: out of memory!\n");
+- return AVERROR(EINVAL);
+- }
+-
+- av_log(ctx, AV_LOG_INFO, "Stabilize: init %s\n", LIBVIDSTAB_VERSION);
+- if(args)
+- sd->options=av_strdup(args);
+- else
+- sd->options=0;
+-
+-
+- return 0;
+-}
+-
+-///1
+-static av_cold void uninit(AVFilterContext *ctx)
+-{
+- StabData *sd = ctx->priv;
+-
+- // avfilter_unref_buffer(sd->ref);
+-
+- MotionDetect* md = &(sd->md);
+- if (sd->f) {
+- fclose(sd->f);
+- sd->f = NULL;
+- }
+-
+- cleanupMotionDetection(md);
+- if (sd->result) {
+- av_free(sd->result);
+- sd->result = NULL;
+- }
+- if(sd->options) av_free(sd->options);
+-}
+-
+-// AVFILTER_DEFINE_CLASS(stabilize);
+-
+-static int query_formats(AVFilterContext *ctx)
+-{
+- static const enum AVPixelFormat pix_fmts[] = {
+- AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
+- AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA420P,
+- AV_PIX_FMT_YUV440P, AV_PIX_FMT_GRAY8,
+- AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGBA,
+- AV_PIX_FMT_NONE
+- };
+-
+- ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
+- return 0;
+-}
+-
+-
+-
+-
+-static int config_input(AVFilterLink *inlink)
+-{
+- AVFilterContext *ctx = inlink->dst;
+- StabData *sd = ctx->priv;
+-// char* filenamecopy, *filebasename;
+-
+- MotionDetect* md = &(sd->md);
+- VSFrameInfo fi;
+- const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[inlink->format];
+-
+- initFrameInfo(&fi,inlink->w, inlink->h, AV2OurPixelFormat(ctx, inlink->format));
+- // check
+- if(fi.bytesPerPixel != av_get_bits_per_pixel(desc)/8)
+- av_log(ctx, AV_LOG_ERROR, "pixel-format error: wrong bits/per/pixel");
+- if(fi.log2ChromaW != desc->log2_chroma_w)
+- av_log(ctx, AV_LOG_ERROR, "pixel-format error: log2_chroma_w");
+- if(fi.log2ChromaH != desc->log2_chroma_h)
+- av_log(ctx, AV_LOG_ERROR, "pixel-format error: log2_chroma_h");
+-
+- if(initMotionDetect(md, &fi, "stabilize") != VS_OK){
+- av_log(ctx, AV_LOG_ERROR, "initialization of Motion Detection failed");
+- return AVERROR(EINVAL);
+- }
+-
+- /// TODO: find out input name
+- sd->result = av_malloc(VS_INPUT_MAXLEN);
+-// filenamecopy = strndup(sd->vob->video_in_file);
+-// filebasename = basename(filenamecopy);
+-// if (strlen(filebasename) < VS_INPUT_MAXLEN - 4) {
+-// snprintf(sd->result, VS_INPUT_MAXLEN, "%s.trf", filebasename);
+-//} else {
+-// av_log(ctx, AV_LOG_WARN, "input name too long, using default `%s'",
+-// DEFAULT_TRANS_FILE_NAME);
+- snprintf(sd->result, VS_INPUT_MAXLEN, DEFAULT_TRANS_FILE_NAME);
+-// }
+-
+- if (sd->options != NULL) {
+- if(optstr_lookup(sd->options, "help")) {
+- av_log(ctx, AV_LOG_INFO, motiondetect_help);
+- return AVERROR(EINVAL);
+- }
+-
+- optstr_get(sd->options, "result", "%[^:]", sd->result);
+- optstr_get(sd->options, "shakiness", "%d", &md->shakiness);
+- optstr_get(sd->options, "accuracy", "%d", &md->accuracy);
+- optstr_get(sd->options, "stepsize", "%d", &md->stepSize);
+- optstr_get(sd->options, "algo", "%d", &md->algo);
+- optstr_get(sd->options, "mincontrast","%lf",&md->contrastThreshold);
+- optstr_get(sd->options, "show", "%d", &md->show);
+- }
+-
+- if(configureMotionDetect(md)!= VS_OK){
+- av_log(ctx, AV_LOG_ERROR, "configuration of Motion Detection failed\n");
+- return AVERROR(EINVAL);
+- }
+-
+- av_log(ctx, AV_LOG_INFO, "Image Stabilization Settings:\n");
+- av_log(ctx, AV_LOG_INFO, " shakiness = %d\n", md->shakiness);
+- av_log(ctx, AV_LOG_INFO, " accuracy = %d\n", md->accuracy);
+- av_log(ctx, AV_LOG_INFO, " stepsize = %d\n", md->stepSize);
+- av_log(ctx, AV_LOG_INFO, " algo = %d\n", md->algo);
+- av_log(ctx, AV_LOG_INFO, " mincontrast = %f\n", md->contrastThreshold);
+- av_log(ctx, AV_LOG_INFO, " show = %d\n", md->show);
+- av_log(ctx, AV_LOG_INFO, " result = %s\n", sd->result);
+-
+- sd->f = fopen(sd->result, "w");
+- if (sd->f == NULL) {
+- av_log(ctx, AV_LOG_ERROR, "cannot open transform file %s!\n", sd->result);
+- return AVERROR(EINVAL);
+- }else{
+- if(prepareFile(md, sd->f) != VS_OK){
+- av_log(ctx, AV_LOG_ERROR, "cannot write to transform file %s!\n", sd->result);
+- return AVERROR(EINVAL);
+- }
+- }
+- return 0;
+-}
+-
+-
+-static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
+-{
+- AVFilterContext *ctx = inlink->dst;
+- StabData *sd = ctx->priv;
+- MotionDetect* md = &(sd->md);
+- LocalMotions localmotions;
+-
+-
+- AVFilterLink *outlink = inlink->dst->outputs[0];
+- //const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+- //int hsub0 = desc->log2_chroma_w;
+- //int vsub0 = desc->log2_chroma_h;
+- int direct = 0;
+- AVFilterBufferRef *out;
+- VSFrame frame;
+- int plane;
+-
+- if (in->perms & AV_PERM_WRITE) {
+- direct = 1;
+- out = in;
+- } else {
+- out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+- if (!out) {
+- avfilter_unref_bufferp(&in);
+- return AVERROR(ENOMEM);
+- }
+- avfilter_copy_buffer_ref_props(out, in);
+- }
+-
+- for(plane=0; plane < md->fi.planes; plane++){
+- frame.data[plane] = in->data[plane];
+- frame.linesize[plane] = in->linesize[plane];
+- }
+- if(motionDetection(md, &localmotions, &frame) != VS_OK){
+- av_log(ctx, AV_LOG_ERROR, "motion detection failed");
+- return AVERROR(AVERROR_EXTERNAL);
+- } else {
+- if(writeToFile(md, sd->f, &localmotions) != VS_OK){
+- av_log(ctx, AV_LOG_ERROR, "cannot write to transform file!");
+- return AVERROR(EPERM);
+- }
+- vs_vector_del(&localmotions);
+- }
+- if(md->show>0 && !direct){
+- // copy
+- av_image_copy(out->data, out->linesize,
+- (void*)in->data, in->linesize,
+- in->format, in->video->w, in->video->h);
+- }
+-
+- if (!direct)
+- avfilter_unref_bufferp(&in);
+-
+- return ff_filter_frame(outlink, out);
+-}
+-
+-
+-AVFilter avfilter_vf_stabilize = {
+- .name = "stabilize",
+- .description = NULL_IF_CONFIG_SMALL("extracts relative transformations of \n\
+- subsequent frames (used for stabilization together with the\n\
+- transform filter in a second pass)."),
+-
+- .priv_size = sizeof(StabData),
+-
+- .init = init,
+- .uninit = uninit,
+- .query_formats = query_formats,
+-
+- .inputs = (const AVFilterPad[]) {{ .name = "default",
+- .type = AVMEDIA_TYPE_VIDEO,
+- .get_video_buffer = ff_null_get_video_buffer,
+- .filter_frame = filter_frame,
+- .config_props = config_input,
+- .min_perms = AV_PERM_READ, },
+- { .name = NULL}},
+- .outputs = (const AVFilterPad[]) {{ .name = "default",
+- .type = AVMEDIA_TYPE_VIDEO, },
+- { .name = NULL}},
+-};
+-
+-
+-
+-/*************************************************************************/
+-
+-/*
+- * Local variables:
+- * c-file-style: "stroustrup"
+- * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+- * indent-tabs-mode: nil
+- * End:
+- *
+- * vim: expandtab shiftwidth=4:
+- */
+diff --git a/libavfilter/vf_transform.c b/libavfilter/vf_transform.c
+deleted file mode 100644
+index d8a7d99..0000000
+--- a/libavfilter/vf_transform.c
++++ /dev/null
+@@ -1,349 +0,0 @@
+-/*
+- * vf_transform.c
+- *
+- * Copyright (C) Georg Martius - Jan 2012
+- * georg dot martius at web dot de
+- *
+- * This file is part of vid.stab, video deshaking lib
+- *
+- * vid.stab 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, or (at your option)
+- * any later version.
+- *
+- * vid.stab 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 GNU Make; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-/* Typical call:
+- * ffmpeg -i inp.mpeg ffmpeg -vf transform inp_s.mpeg
+- * all parameters are optional
+- */
+-
+-/*
+- TODO: check AVERROR codes
+-*/
+-
+-#define DEFAULT_TRANS_FILE_NAME "transforms.dat"
+-
+-#include "libavutil/common.h"
+-#include "libavutil/mem.h"
+-#include "libavutil/pixdesc.h"
+-#include "libavutil/pixfmt.h"
+-#include "libavcodec/dsputil.h"
+-#include "avfilter.h"
+-#include "formats.h"
+-#include "internal.h"
+-#include "video.h"
+-
+-#include "optstr.h"
+-
+-#include "vid.stab/libvidstab.h"
+-
+-#define VS_INPUT_MAXLEN 1024
+-
+-/* private date structure of this filter*/
+-typedef struct {
+- TransformData td;
+-
+- Transformations trans; // transformations
+- char* options;
+- char input[VS_INPUT_MAXLEN];
+-} FilterData;
+-
+-
+-static PixelFormat AV2OurPixelFormat(AVFilterContext *ctx, enum AVPixelFormat pf){
+- switch(pf){
+- case AV_PIX_FMT_YUV420P: return PF_YUV420P;
+- case AV_PIX_FMT_RGB24: return PF_RGB24;
+- case AV_PIX_FMT_BGR24: return PF_BGR24;
+- case AV_PIX_FMT_YUV422P: return PF_YUV422P;
+- case AV_PIX_FMT_YUV444P: return PF_YUV444P;
+- case AV_PIX_FMT_YUV410P: return PF_YUV410P;
+- case AV_PIX_FMT_YUV411P: return PF_YUV411P;
+- case AV_PIX_FMT_GRAY8: return PF_GRAY8;
+- case AV_PIX_FMT_YUVA420P:return PF_YUVA420P;
+- case AV_PIX_FMT_RGBA: return PF_RGBA;
+- default:
+- av_log(ctx, AV_LOG_ERROR, "cannot deal with pixel format %i!\n", pf);
+- return PF_NONE;
+- }
+-}
+-
+-
+-/*************************************************************************/
+-
+-/* Module interface routines and data. */
+-
+-/*************************************************************************/
+-
+-static av_cold int init(AVFilterContext *ctx, const char *args)
+-{
+-
+- FilterData* fd = ctx->priv;
+-
+- if (!fd) {
+- av_log(ctx, AV_LOG_INFO, "init: out of memory!\n");
+- return AVERROR(EINVAL);
+- }
+-
+- av_log(ctx, AV_LOG_INFO, "Transform filter: init %s\n", LIBVIDSTAB_VERSION);
+-
+- if(args)
+- fd->options=av_strdup(args);
+-
+- return 0;
+-}
+-
+-static av_cold void uninit(AVFilterContext *ctx)
+-{
+- FilterData *fd = ctx->priv;
+-
+- // avfilter_unref_buffer(fd->ref);
+-
+- cleanupTransformData(&fd->td);
+- cleanupTransformations(&fd->trans);
+-
+- if(fd->options) av_free(fd->options);
+-}
+-
+-
+-static int query_formats(AVFilterContext *ctx)
+-{
+- static const enum AVPixelFormat pix_fmts[] = {
+- AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
+- AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA420P,
+- AV_PIX_FMT_YUV440P, AV_PIX_FMT_GRAY8,
+- AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGBA,
+- AV_PIX_FMT_NONE
+- };
+-
+- ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
+- return 0;
+-}
+-
+-
+-static int config_input(AVFilterLink *inlink)
+-{
+- AVFilterContext *ctx = inlink->dst;
+- FilterData *fd = ctx->priv;
+- FILE* f;
+-// char* filenamecopy, *filebasename;
+-
+- const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[inlink->format];
+-
+- TransformData* td = &(fd->td);
+-
+- VSFrameInfo fi_src;
+- VSFrameInfo fi_dest;
+- if(!initFrameInfo(&fi_src, inlink->w, inlink->h,
+- AV2OurPixelFormat(ctx,inlink->format)) ||
+- !initFrameInfo(&fi_dest, inlink->w, inlink->h,
+- AV2OurPixelFormat(ctx, inlink->format))){
+- av_log(ctx, AV_LOG_ERROR, "unknown pixel format: %i (%s)",
+- inlink->format, desc->name);
+- return AVERROR(EINVAL);
+- }
+-
+- // check
+- if(fi_src.bytesPerPixel != av_get_bits_per_pixel(desc)/8 ||
+- fi_src.log2ChromaW != desc->log2_chroma_w ||
+- fi_src.log2ChromaH != desc->log2_chroma_h){
+- av_log(ctx, AV_LOG_ERROR, "pixel-format error: bpp %i<>%i ",
+- fi_src.bytesPerPixel, av_get_bits_per_pixel(desc)/8);
+- av_log(ctx, AV_LOG_ERROR, "chroma_subsampl: w: %i<>%i h: %i<>%i\n",
+- fi_src.log2ChromaW, desc->log2_chroma_w,
+- fi_src.log2ChromaH, desc->log2_chroma_h);
+- return AVERROR(EINVAL);
+- }
+-
+- if(initTransformData(td, &fi_src, &fi_dest, "transform") != VS_OK){
+- av_log(ctx, AV_LOG_ERROR, "initialization of TransformData failed\n");
+- return AVERROR(EINVAL);
+- }
+- td->verbose=1; // TODO: get from somewhere
+-
+-
+- /// TODO: find out input name
+-// fd->input = (char*)av_malloc(VS_INPUT_MAXLEN);
+-
+-// filenamecopy = strndup(fd->vob->video_in_file);
+-// filebasename = basename(filenamecopy);
+-// if (strlen(filebasename) < VS_INPUT_MAXLEN - 4) {
+-// snprintf(fd->result, VS_INPUT_MAXLEN, "%s.trf", filebasename);
+-//} else {
+-// av_log(ctx, AV_LOG_WARN, "input name too long, using default `%s'",
+-// DEFAULT_TRANS_FILE_NAME);
+- snprintf(fd->input, VS_INPUT_MAXLEN, DEFAULT_TRANS_FILE_NAME);
+-// }
+-
+- if (fd->options != NULL) {
+- if(optstr_lookup(fd->options, "help")) {
+- av_log(ctx, AV_LOG_INFO, transform_help);
+- return AVERROR(EINVAL);
+- }
+-
+- optstr_get(fd->options, "input", "%[^:]", fd->input);
+- optstr_get(fd->options, "maxshift", "%d", &td->maxShift);
+- optstr_get(fd->options, "maxangle", "%lf", &td->maxAngle);
+- optstr_get(fd->options, "smoothing", "%d", &td->smoothing);
+- optstr_get(fd->options, "crop" , "%d", &td->crop);
+- optstr_get(fd->options, "invert" , "%d", &td->invert);
+- optstr_get(fd->options, "relative" , "%d", &td->relative);
+- optstr_get(fd->options, "zoom" , "%lf",&td->zoom);
+- optstr_get(fd->options, "optzoom" , "%d", &td->optZoom);
+- optstr_get(fd->options, "interpol" , "%d", (int*)(&td->interpolType));
+- optstr_get(fd->options, "sharpen" , "%lf",&td->sharpen);
+- if(optstr_lookup(fd->options, "tripod")){
+- av_log(ctx,AV_LOG_INFO, "Virtual tripod mode: relative=False, smoothing=0");
+- td->relative=0;
+- td->smoothing=0;
+- }
+- }
+-
+- if(configureTransformData(td)!= VS_OK){
+- av_log(ctx, AV_LOG_ERROR, "configuration of Tranform failed\n");
+- return AVERROR(EINVAL);
+- }
+-
+- av_log(ctx, AV_LOG_INFO, "Image Transformation/Stabilization Settings:\n");
+- av_log(ctx, AV_LOG_INFO, " input = %s\n", fd->input);
+- av_log(ctx, AV_LOG_INFO, " smoothing = %d\n", td->smoothing);
+- av_log(ctx, AV_LOG_INFO, " maxshift = %d\n", td->maxShift);
+- av_log(ctx, AV_LOG_INFO, " maxangle = %f\n", td->maxAngle);
+- av_log(ctx, AV_LOG_INFO, " crop = %s\n", td->crop ? "Black" : "Keep");
+- av_log(ctx, AV_LOG_INFO, " relative = %s\n", td->relative ? "True": "False");
+- av_log(ctx, AV_LOG_INFO, " invert = %s\n", td->invert ? "True" : "False");
+- av_log(ctx, AV_LOG_INFO, " zoom = %f\n", td->zoom);
+- av_log(ctx, AV_LOG_INFO, " optzoom = %s\n", td->optZoom ? "On" : "Off");
+- av_log(ctx, AV_LOG_INFO, " interpol = %s\n", interpolTypes[td->interpolType]);
+- av_log(ctx, AV_LOG_INFO, " sharpen = %f\n", td->sharpen);
+-
+- f = fopen(fd->input, "r");
+- if (f == NULL) {
+- av_log(ctx, AV_LOG_ERROR, "cannot open input file %s!\n", fd->input);
+- } else {
+- ManyLocalMotions mlms;
+- if(readLocalMotionsFile(f,&mlms)==VS_OK){
+- // calculate the actual transforms from the localmotions
+- if(localmotions2TransformsSimple(td, &mlms,&fd->trans)!=VS_OK)
+- av_log(ctx, AV_LOG_ERROR, "calculating transformations failed!\n");
+- }else{ // try to read old format
+- if (!readOldTransforms(td, f, &fd->trans)) { /* read input file */
+- av_log(ctx, AV_LOG_ERROR, "error parsing input file %s!\n", fd->input);
+- }
+- }
+- }
+- fclose(f);
+-
+- if (preprocessTransforms(td, &fd->trans)!= VS_OK ) {
+- av_log(ctx, AV_LOG_ERROR, "error while preprocessing transforms\n");
+- return AVERROR(EINVAL);
+- }
+-
+- // TODO: add sharpening
+- return 0;
+-}
+-
+-
+-static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
+-{
+- AVFilterContext *ctx = inlink->dst;
+- FilterData *fd = ctx->priv;
+- TransformData* td = &(fd->td);
+-
+- AVFilterLink *outlink = inlink->dst->outputs[0];
+- //const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+- //int hsub0 = desc->log2_chroma_w;
+- //int vsub0 = desc->log2_chroma_h;
+- int direct = 0;
+- AVFilterBufferRef *out;
+- VSFrame inframe;
+- VSFrame outframe;
+- int plane;
+-
+- if (in->perms & AV_PERM_WRITE) {
+- direct = 1;
+- out = in;
+- } else {
+- out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+- if (!out) {
+- avfilter_unref_bufferp(&in);
+- return AVERROR(ENOMEM);
+- }
+- avfilter_copy_buffer_ref_props(out, in);
+- }
+-
+- for(plane=0; plane < td->fiSrc.planes; plane++){
+- inframe.data[plane] = in->data[plane];
+- inframe.linesize[plane] = in->linesize[plane];
+- }
+- for(plane=0; plane < td->fiDest.planes; plane++){
+- outframe.data[plane] = out->data[plane];
+- outframe.linesize[plane] = out->linesize[plane];
+- }
+-
+-
+- transformPrepare(td, &inframe, &outframe);
+-
+- if (fd->td.fiSrc.pFormat > PF_PACKED) {
+- transformRGB(td, getNextTransform(td, &fd->trans));
+- } else {
+- transformYUV(td, getNextTransform(td, &fd->trans));
+- }
+- transformFinish(td);
+-
+- if (!direct)
+- avfilter_unref_bufferp(&in);
+-
+- return ff_filter_frame(outlink, out);
+-}
+-
+-
+-AVFilter avfilter_vf_transform = {
+- .name = "transform",
+- .description = NULL_IF_CONFIG_SMALL("transforms each frame according to transformations\n\
+- given in an input file (e.g. translation, rotate) see also filter stabilize."),
+-
+- .priv_size = sizeof(FilterData),
+-
+- .init = init,
+- .uninit = uninit,
+- .query_formats = query_formats,
+-
+- .inputs = (const AVFilterPad[]) {
+- { .name = "default",
+- .type = AVMEDIA_TYPE_VIDEO,
+- .get_video_buffer = ff_null_get_video_buffer,
+- .filter_frame = filter_frame,
+- .config_props = config_input,
+- .min_perms = AV_PERM_READ | AV_PERM_WRITE,
+- },
+- { .name = NULL}},
+- .outputs = (const AVFilterPad[]) {
+- { .name = "default",
+- .type = AVMEDIA_TYPE_VIDEO, },
+- { .name = NULL}
+- },
+-};
+-
+-
+-
+-/*************************************************************************/
+-
+-/*
+- * Local variables:
+- * c-file-style: "stroustrup"
+- * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+- * indent-tabs-mode: nil
+- * End:
+- *
+- * vim: expandtab shiftwidth=4:
+- */
+diff --git a/libavfilter/vf_vidstabdetect.c b/libavfilter/vf_vidstabdetect.c
+new file mode 100644
+index 0000000..d96ca8e
+--- /dev/null
++++ b/libavfilter/vf_vidstabdetect.c
+@@ -0,0 +1,218 @@
++/*
++ * Copyright (c) 2013 Georg Martius <georg dot martius at web dot de>
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#define DEFAULT_RESULT_NAME "transforms.trf"
++
++#include <vid.stab/libvidstab.h>
++
++#include "libavutil/common.h"
++#include "libavutil/opt.h"
++#include "libavutil/imgutils.h"
++#include "avfilter.h"
++#include "internal.h"
++
++#include "vidstabutils.h"
++
++typedef struct {
++ const AVClass *class;
++
++ VSMotionDetect md;
++ VSMotionDetectConfig conf;
++
++ char *result;
++ FILE *f;
++} StabData;
++
++
++#define OFFSET(x) offsetof(StabData, x)
++#define OFFSETC(x) (offsetof(StabData, conf)+offsetof(VSMotionDetectConfig, x))
++#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
++
++static const AVOption vidstabdetect_options[] = {
++ {"result", "path to the file used to write the transforms", OFFSET(result), AV_OPT_TYPE_STRING, {.str = DEFAULT_RESULT_NAME}, .flags = FLAGS},
++ {"shakiness", "how shaky is the video and how quick is the camera?"
++ " 1: little (fast) 10: very strong/quick (slow)", OFFSETC(shakiness), AV_OPT_TYPE_INT, {.i64 = 5}, 1, 10, FLAGS},
++ {"accuracy", "(>=shakiness) 1: low 15: high (slow)", OFFSETC(accuracy), AV_OPT_TYPE_INT, {.i64 = 9}, 1, 15, FLAGS},
++ {"stepsize", "region around minimum is scanned with 1 pixel resolution", OFFSETC(stepSize), AV_OPT_TYPE_INT, {.i64 = 6}, 1, 32, FLAGS},
++ {"mincontrast", "below this contrast a field is discarded (0-1)", OFFSETC(contrastThreshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.25}, 0.0, 1.0, FLAGS},
++ {"show", "0: draw nothing; 1,2: show fields and transforms", OFFSETC(show), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 2, FLAGS},
++ {"tripod", "virtual tripod mode (if >0): motion is compared to a reference"
++ " reference frame (frame # is the value)", OFFSETC(virtualTripod), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS},
++ {NULL}
++};
++
++AVFILTER_DEFINE_CLASS(vidstabdetect);
++
++static av_cold int init(AVFilterContext *ctx)
++{
++ StabData *sd = ctx->priv;
++ vs_set_mem_and_log_functions();
++ sd->class = &vidstabdetect_class;
++ av_log(ctx, AV_LOG_VERBOSE, "vidstabdetect filter: init %s\n", LIBVIDSTAB_VERSION);
++ return 0;
++}
++
++static av_cold void uninit(AVFilterContext *ctx)
++{
++ StabData *sd = ctx->priv;
++ VSMotionDetect *md = &(sd->md);
++
++ if (sd->f) {
++ fclose(sd->f);
++ sd->f = NULL;
++ }
++
++ vsMotionDetectionCleanup(md);
++}
++
++static int query_formats(AVFilterContext *ctx)
++{
++ // If you add something here also add it in vidstabutils.c
++ static const enum AVPixelFormat pix_fmts[] = {
++ AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
++ AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA420P,
++ AV_PIX_FMT_YUV440P, AV_PIX_FMT_GRAY8,
++ AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGBA,
++ AV_PIX_FMT_NONE
++ };
++
++ ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
++ return 0;
++}
++
++static int config_input(AVFilterLink *inlink)
++{
++ AVFilterContext *ctx = inlink->dst;
++ StabData *sd = ctx->priv;
++
++ VSMotionDetect* md = &(sd->md);
++ VSFrameInfo fi;
++ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
++
++ vsFrameInfoInit(&fi, inlink->w, inlink->h, av_2_vs_pixel_format(ctx, inlink->format));
++ if (fi.bytesPerPixel != av_get_bits_per_pixel(desc)/8) {
++ av_log(ctx, AV_LOG_ERROR, "pixel-format error: wrong bits/per/pixel, please report a BUG");
++ return AVERROR(EINVAL);
++ }
++ if (fi.log2ChromaW != desc->log2_chroma_w) {
++ av_log(ctx, AV_LOG_ERROR, "pixel-format error: log2_chroma_w, please report a BUG");
++ return AVERROR(EINVAL);
++ }
++
++ if (fi.log2ChromaH != desc->log2_chroma_h) {
++ av_log(ctx, AV_LOG_ERROR, "pixel-format error: log2_chroma_h, please report a BUG");
++ return AVERROR(EINVAL);
++ }
++
++ // set values that are not initialized by the options
++ sd->conf.algo = 1;
++ sd->conf.modName = "vidstabdetect";
++ if (vsMotionDetectInit(md, &sd->conf, &fi) != VS_OK) {
++ av_log(ctx, AV_LOG_ERROR, "initialization of Motion Detection failed, please report a BUG");
++ return AVERROR(EINVAL);
++ }
++
++ vsMotionDetectGetConfig(&sd->conf, md);
++ av_log(ctx, AV_LOG_INFO, "Video stabilization settings (pass 1/2):\n");
++ av_log(ctx, AV_LOG_INFO, " shakiness = %d\n", sd->conf.shakiness);
++ av_log(ctx, AV_LOG_INFO, " accuracy = %d\n", sd->conf.accuracy);
++ av_log(ctx, AV_LOG_INFO, " stepsize = %d\n", sd->conf.stepSize);
++ av_log(ctx, AV_LOG_INFO, " mincontrast = %f\n", sd->conf.contrastThreshold);
++ av_log(ctx, AV_LOG_INFO, " show = %d\n", sd->conf.show);
++ av_log(ctx, AV_LOG_INFO, " result = %s\n", sd->result);
++
++ sd->f = fopen(sd->result, "w");
++ if (sd->f == NULL) {
++ av_log(ctx, AV_LOG_ERROR, "cannot open transform file %s\n", sd->result);
++ return AVERROR(EINVAL);
++ } else {
++ if (vsPrepareFile(md, sd->f) != VS_OK) {
++ av_log(ctx, AV_LOG_ERROR, "cannot write to transform file %s\n", sd->result);
++ return AVERROR(EINVAL);
++ }
++ }
++ return 0;
++}
++
++
++static int filter_frame(AVFilterLink *inlink, AVFrame *in)
++{
++ AVFilterContext *ctx = inlink->dst;
++ StabData *sd = ctx->priv;
++ VSMotionDetect *md = &(sd->md);
++ LocalMotions localmotions;
++
++ AVFilterLink *outlink = inlink->dst->outputs[0];
++ VSFrame frame;
++ int plane;
++
++ if (sd->conf.show > 0 && !av_frame_is_writable(in))
++ av_frame_make_writable(in);
++
++ for (plane = 0; plane < md->fi.planes; plane++) {
++ frame.data[plane] = in->data[plane];
++ frame.linesize[plane] = in->linesize[plane];
++ }
++ if (vsMotionDetection(md, &localmotions, &frame) != VS_OK) {
++ av_log(ctx, AV_LOG_ERROR, "motion detection failed");
++ return AVERROR(AVERROR_EXTERNAL);
++ } else {
++ if (vsWriteToFile(md, sd->f, &localmotions) != VS_OK) {
++ av_log(ctx, AV_LOG_ERROR, "cannot write to transform file");
++ return AVERROR(errno);
++ }
++ vs_vector_del(&localmotions);
++ }
++
++ return ff_filter_frame(outlink, in);
++}
++
++static const AVFilterPad avfilter_vf_vidstabdetect_inputs[] = {
++ {
++ .name = "default",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .filter_frame = filter_frame,
++ .config_props = config_input,
++ },
++ { NULL }
++};
++
++static const AVFilterPad avfilter_vf_vidstabdetect_outputs[] = {
++ {
++ .name = "default",
++ .type = AVMEDIA_TYPE_VIDEO,
++ },
++ { NULL }
++};
++
++AVFilter avfilter_vf_vidstabdetect = {
++ .name = "vidstabdetect",
++ .description = NULL_IF_CONFIG_SMALL("Extract relative transformations, "
++ "pass 1 of 2 for stabilization "
++ "(see vidstabtransform for pass 2)."),
++ .priv_size = sizeof(StabData),
++ .init = init,
++ .uninit = uninit,
++ .query_formats = query_formats,
++
++ .inputs = avfilter_vf_vidstabdetect_inputs,
++ .outputs = avfilter_vf_vidstabdetect_outputs,
++ .priv_class = &vidstabdetect_class,
++};
+diff --git a/libavfilter/vf_vidstabtransform.c b/libavfilter/vf_vidstabtransform.c
+new file mode 100644
+index 0000000..eee3da7
+--- /dev/null
++++ b/libavfilter/vf_vidstabtransform.c
+@@ -0,0 +1,292 @@
++/*
++ * Copyright (c) 2013 Georg Martius <georg dot martius at web dot de>
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#define DEFAULT_INPUT_NAME "transforms.trf"
++
++#include <vid.stab/libvidstab.h>
++
++#include "libavutil/common.h"
++#include "libavutil/opt.h"
++#include "libavutil/imgutils.h"
++#include "avfilter.h"
++#include "internal.h"
++
++#include "vidstabutils.h"
++
++typedef struct {
++ const AVClass *class;
++
++ VSTransformData td;
++ VSTransformConfig conf;
++
++ VSTransformations trans; // transformations
++ char *input; // name of transform file
++ int tripod;
++} TransformContext;
++
++#define OFFSET(x) offsetof(TransformContext, x)
++#define OFFSETC(x) (offsetof(TransformContext, conf)+offsetof(VSTransformConfig, x))
++#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
++
++static const AVOption vidstabtransform_options[] = {
++ {"input", "path to the file storing the transforms", OFFSET(input),
++ AV_OPT_TYPE_STRING, {.str = DEFAULT_INPUT_NAME}, .flags = FLAGS },
++ {"smoothing", "number of frames*2 + 1 used for lowpass filtering", OFFSETC(smoothing),
++ AV_OPT_TYPE_INT, {.i64 = 10}, 1, 1000, FLAGS},
++ {"maxshift", "maximal number of pixels to translate image", OFFSETC(maxShift),
++ AV_OPT_TYPE_INT, {.i64 = -1}, -1, 500, FLAGS},
++ {"maxangle", "maximal angle in rad to rotate image", OFFSETC(maxAngle),
++ AV_OPT_TYPE_DOUBLE, {.dbl = -1.0}, -1.0, 3.14, FLAGS},
++ {"crop", "set cropping mode", OFFSETC(crop),
++ AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS, "crop"},
++ { "keep", "keep border", 0,
++ AV_OPT_TYPE_CONST, {.i64 = VSKeepBorder }, 0, 0, FLAGS, "crop"},
++ { "black", "black border", 0,
++ AV_OPT_TYPE_CONST, {.i64 = VSCropBorder }, 0, 0, FLAGS, "crop"},
++ {"invert", "1: invert transforms", OFFSETC(invert),
++ AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS},
++ {"relative", "consider transforms as 0: absolute, 1: relative", OFFSETC(relative),
++ AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, FLAGS},
++ {"zoom", "percentage to zoom >0: zoom in, <0 zoom out", OFFSETC(zoom),
++ AV_OPT_TYPE_DOUBLE, {.dbl = 0}, 0, 100, FLAGS},
++ {"optzoom", "0: nothing, 1: determine optimal zoom (added to 'zoom')", OFFSETC(optZoom),
++ AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, FLAGS},
++ {"interpol", "type of interpolation", OFFSETC(interpolType),
++ AV_OPT_TYPE_INT, {.i64 = 2}, 0, 3, FLAGS, "interpol"},
++ { "no", "no interpolation", 0,
++ AV_OPT_TYPE_CONST, {.i64 = VS_Zero }, 0, 0, FLAGS, "interpol"},
++ { "linear", "linear (horizontal)", 0,
++ AV_OPT_TYPE_CONST, {.i64 = VS_Linear }, 0, 0, FLAGS, "interpol"},
++ { "bilinear","bi-linear", 0,
++ AV_OPT_TYPE_CONST, {.i64 = VS_BiLinear},0, 0, FLAGS, "interpol"},
++ { "bicubic", "bi-cubic", 0,
++ AV_OPT_TYPE_CONST, {.i64 = VS_BiCubic },0, 0, FLAGS, "interpol"},
++ {"tripod", "if 1: virtual tripod mode (equiv. to relative=0:smoothing=0)", OFFSET(tripod),
++ AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS},
++ {NULL}
++};
++
++AVFILTER_DEFINE_CLASS(vidstabtransform);
++
++static av_cold int init(AVFilterContext *ctx)
++{
++ TransformContext *tc = ctx->priv;
++ vs_set_mem_and_log_functions();
++ tc->class = &vidstabtransform_class;
++ av_log(ctx, AV_LOG_VERBOSE, "vidstabtransform filter: init %s\n", LIBVIDSTAB_VERSION);
++ return 0;
++}
++
++static av_cold void uninit(AVFilterContext *ctx)
++{
++ TransformContext *tc = ctx->priv;
++
++ vsTransformDataCleanup(&tc->td);
++ vsTransformationsCleanup(&tc->trans);
++}
++
++static int query_formats(AVFilterContext *ctx)
++{
++ // If you add something here also add it in vidstabutils.c
++ static const enum AVPixelFormat pix_fmts[] = {
++ AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
++ AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA420P,
++ AV_PIX_FMT_YUV440P, AV_PIX_FMT_GRAY8,
++ AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGBA,
++ AV_PIX_FMT_NONE
++ };
++
++ ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
++ return 0;
++}
++
++
++static int config_input(AVFilterLink *inlink)
++{
++ AVFilterContext *ctx = inlink->dst;
++ TransformContext *tc = ctx->priv;
++ FILE *f;
++
++ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
++
++ VSTransformData *td = &(tc->td);
++
++ VSFrameInfo fi_src;
++ VSFrameInfo fi_dest;
++
++ if (!vsFrameInfoInit(&fi_src, inlink->w, inlink->h,
++ av_2_vs_pixel_format(ctx, inlink->format)) ||
++ !vsFrameInfoInit(&fi_dest, inlink->w, inlink->h,
++ av_2_vs_pixel_format(ctx, inlink->format))) {
++ av_log(ctx, AV_LOG_ERROR, "unknown pixel format: %i (%s)",
++ inlink->format, desc->name);
++ return AVERROR(EINVAL);
++ }
++
++ if (fi_src.bytesPerPixel != av_get_bits_per_pixel(desc)/8 ||
++ fi_src.log2ChromaW != desc->log2_chroma_w ||
++ fi_src.log2ChromaH != desc->log2_chroma_h) {
++ av_log(ctx, AV_LOG_ERROR, "pixel-format error: bpp %i<>%i ",
++ fi_src.bytesPerPixel, av_get_bits_per_pixel(desc)/8);
++ av_log(ctx, AV_LOG_ERROR, "chroma_subsampl: w: %i<>%i h: %i<>%i\n",
++ fi_src.log2ChromaW, desc->log2_chroma_w,
++ fi_src.log2ChromaH, desc->log2_chroma_h);
++ return AVERROR(EINVAL);
++ }
++
++ // set values that are not initializes by the options
++ tc->conf.modName = "vidstabtransform";
++ tc->conf.verbose =1;
++ if (tc->tripod) {
++ av_log(ctx, AV_LOG_INFO, "Virtual tripod mode: relative=0, smoothing=0");
++ tc->conf.relative = 0;
++ tc->conf.smoothing = 0;
++ }
++
++ if (vsTransformDataInit(td, &tc->conf, &fi_src, &fi_dest) != VS_OK) {
++ av_log(ctx, AV_LOG_ERROR, "initialization of vid.stab transform failed, please report a BUG\n");
++ return AVERROR(EINVAL);
++ }
++
++ vsTransformGetConfig(&tc->conf, td);
++ av_log(ctx, AV_LOG_INFO, "Video transformation/stabilization settings (pass 2/2):\n");
++ av_log(ctx, AV_LOG_INFO, " input = %s\n", tc->input);
++ av_log(ctx, AV_LOG_INFO, " smoothing = %d\n", tc->conf.smoothing);
++ av_log(ctx, AV_LOG_INFO, " maxshift = %d\n", tc->conf.maxShift);
++ av_log(ctx, AV_LOG_INFO, " maxangle = %f\n", tc->conf.maxAngle);
++ av_log(ctx, AV_LOG_INFO, " crop = %s\n", tc->conf.crop ? "Black" : "Keep");
++ av_log(ctx, AV_LOG_INFO, " relative = %s\n", tc->conf.relative ? "True": "False");
++ av_log(ctx, AV_LOG_INFO, " invert = %s\n", tc->conf.invert ? "True" : "False");
++ av_log(ctx, AV_LOG_INFO, " zoom = %f\n", tc->conf.zoom);
++ av_log(ctx, AV_LOG_INFO, " optzoom = %s\n", tc->conf.optZoom ? "On" : "Off");
++ av_log(ctx, AV_LOG_INFO, " interpol = %s\n", getInterpolationTypeName(tc->conf.interpolType));
++
++ f = fopen(tc->input, "r");
++ if (f == NULL) {
++ av_log(ctx, AV_LOG_ERROR, "cannot open input file %s\n", tc->input);
++ return AVERROR(errno);
++ } else {
++ VSManyLocalMotions mlms;
++ if (vsReadLocalMotionsFile(f, &mlms) == VS_OK) {
++ // calculate the actual transforms from the local motions
++ if (vsLocalmotions2TransformsSimple(td, &mlms, &tc->trans) != VS_OK) {
++ av_log(ctx, AV_LOG_ERROR, "calculating transformations failed\n");
++ return AVERROR(EINVAL);
++ }
++ } else { // try to read old format
++ if (!vsReadOldTransforms(td, f, &tc->trans)) { /* read input file */
++ av_log(ctx, AV_LOG_ERROR, "error parsing input file %s\n", tc->input);
++ return AVERROR(EINVAL);
++ }
++ }
++ }
++ fclose(f);
++
++ if (vsPreprocessTransforms(td, &tc->trans) != VS_OK ) {
++ av_log(ctx, AV_LOG_ERROR, "error while preprocessing transforms\n");
++ return AVERROR(EINVAL);
++ }
++
++ // TODO: add sharpening, so far the user needs to call the unsharp filter manually
++ return 0;
++}
++
++
++static int filter_frame(AVFilterLink *inlink, AVFrame *in)
++{
++ AVFilterContext *ctx = inlink->dst;
++ TransformContext *tc = ctx->priv;
++ VSTransformData* td = &(tc->td);
++
++ AVFilterLink *outlink = inlink->dst->outputs[0];
++ int direct = 0;
++ AVFrame *out;
++ VSFrame inframe;
++ int plane;
++
++ if (av_frame_is_writable(in)) {
++ direct = 1;
++ out = in;
++ } else {
++ out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
++ if (!out) {
++ av_frame_free(&in);
++ return AVERROR(ENOMEM);
++ }
++ av_frame_copy_props(out, in);
++ }
++
++ for (plane = 0; plane < vsTransformGetSrcFrameInfo(td)->planes; plane++) {
++ inframe.data[plane] = in->data[plane];
++ inframe.linesize[plane] = in->linesize[plane];
++ }
++ if (direct) {
++ vsTransformPrepare(td, &inframe, &inframe);
++ } else { // separate frames
++ VSFrame outframe;
++ for (plane = 0; plane < vsTransformGetDestFrameInfo(td)->planes; plane++) {
++ outframe.data[plane] = out->data[plane];
++ outframe.linesize[plane] = out->linesize[plane];
++ }
++ vsTransformPrepare(td, &inframe, &outframe);
++ }
++
++ vsDoTransform(td, vsGetNextTransform(td, &tc->trans));
++
++ vsTransformFinish(td);
++
++ if (!direct)
++ av_frame_free(&in);
++
++ return ff_filter_frame(outlink, out);
++}
++
++static const AVFilterPad avfilter_vf_vidstabtransform_inputs[] = {
++ {
++ .name = "default",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .filter_frame = filter_frame,
++ .config_props = config_input,
++ },
++ { NULL }
++};
++
++static const AVFilterPad avfilter_vf_vidstabtransform_outputs[] = {
++ {
++ .name = "default",
++ .type = AVMEDIA_TYPE_VIDEO,
++ },
++ { NULL }
++};
++
++AVFilter avfilter_vf_vidstabtransform = {
++ .name = "vidstabtransform",
++ .description = NULL_IF_CONFIG_SMALL("Transform the frames, "
++ "pass 2 of 2 for stabilization "
++ "(see vidstabdetect for pass 1)."),
++ .priv_size = sizeof(TransformContext),
++ .init = init,
++ .uninit = uninit,
++ .query_formats = query_formats,
++
++ .inputs = avfilter_vf_vidstabtransform_inputs,
++ .outputs = avfilter_vf_vidstabtransform_outputs,
++ .priv_class = &vidstabtransform_class,
++};
+diff --git a/libavfilter/vidstabutils.c b/libavfilter/vidstabutils.c
+new file mode 100644
+index 0000000..dd6486d
+--- /dev/null
++++ b/libavfilter/vidstabutils.c
+@@ -0,0 +1,85 @@
++/*
++ * Copyright (c) 2013 Georg Martius <georg dot martius at web dot de>
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "vidstabutils.h"
++
++/** convert AV's pixelformat to vid.stab pixelformat */
++VSPixelFormat av_2_vs_pixel_format(AVFilterContext *ctx, enum AVPixelFormat pf)
++{
++ switch (pf) {
++ case AV_PIX_FMT_YUV420P: return PF_YUV420P;
++ case AV_PIX_FMT_YUV422P: return PF_YUV422P;
++ case AV_PIX_FMT_YUV444P: return PF_YUV444P;
++ case AV_PIX_FMT_YUV410P: return PF_YUV410P;
++ case AV_PIX_FMT_YUV411P: return PF_YUV411P;
++ case AV_PIX_FMT_YUV440P: return PF_YUV440P;
++ case AV_PIX_FMT_YUVA420P: return PF_YUVA420P;
++ case AV_PIX_FMT_GRAY8: return PF_GRAY8;
++ case AV_PIX_FMT_RGB24: return PF_RGB24;
++ case AV_PIX_FMT_BGR24: return PF_BGR24;
++ case AV_PIX_FMT_RGBA: return PF_RGBA;
++ default:
++ av_log(ctx, AV_LOG_ERROR, "cannot deal with pixel format %i\n", pf);
++ return PF_NONE;
++ }
++}
++
++/** struct to hold a valid context for logging from within vid.stab lib */
++typedef struct {
++ const AVClass *class;
++} VS2AVLogCtx;
++
++/** wrapper to log vs_log into av_log */
++static int vs_2_av_log_wrapper(int type, const char *tag, const char *format, ...)
++{
++ va_list ap;
++ VS2AVLogCtx ctx;
++ AVClass class = {
++ .class_name = tag,
++ .item_name = av_default_item_name,
++ .option = 0,
++ .version = LIBAVUTIL_VERSION_INT,
++ .category = AV_CLASS_CATEGORY_FILTER,
++ };
++ ctx.class = &class;
++ va_start(ap, format);
++ av_vlog(&ctx, type, format, ap);
++ va_end(ap);
++ return VS_OK;
++}
++
++/** sets the memory allocation function and logging constants to av versions */
++void vs_set_mem_and_log_functions(void)
++{
++ vs_malloc = av_malloc;
++ vs_zalloc = av_mallocz;
++ vs_realloc = av_realloc;
++ vs_free = av_free;
++
++ VS_ERROR_TYPE = AV_LOG_ERROR;
++ VS_WARN_TYPE = AV_LOG_WARNING;
++ VS_INFO_TYPE = AV_LOG_INFO;
++ VS_MSG_TYPE = AV_LOG_VERBOSE;
++
++ vs_log = vs_2_av_log_wrapper;
++
++ VS_ERROR = 0;
++ VS_OK = 1;
++}
+diff --git a/libavfilter/vidstabutils.h b/libavfilter/vidstabutils.h
+new file mode 100644
+index 0000000..f1c20e6
+--- /dev/null
++++ b/libavfilter/vidstabutils.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (c) 2013 Georg Martius <georg dot martius at web dot de>
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg 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
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef AVFILTER_VIDSTABUTILS_H
++#define AVFILTER_VIDSTABUTILS_H
++
++#include <vid.stab/libvidstab.h>
++
++#include "avfilter.h"
++
++/* ** some conversions from avlib to vid.stab constants and functions *** */
++
++/** converts the pixelformat of avlib into the one of the vid.stab library */
++VSPixelFormat av_2_vs_pixel_format(AVFilterContext *ctx, enum AVPixelFormat pf);
++
++/** sets the memory allocation function and logging constants to av versions */
++void vs_set_mem_and_log_functions(void);
++
++#endif
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index 819e91b..1d10db3 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -5,12 +5,20 @@ SET(CMAKE_BUILTTYPE None)
+
+ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../CMakeModules/")
+
+-#add_definitions( -Wall -O3 -Wno-pointer-sign -DTESTING )
+-add_definitions( -Wall -O3 -Wno-pointer-sign)
+-#add_definitions( -Wall -O0 -g -Wno-pointer-sign )
++include (FindSSE)
++
++set(MAJOR_VERSION 0)
++set(MINOR_VERSION 9)
++set(PATCH_VERSION 6)
++set(VIDSTAB_VERSION ${MAJOR_VERSION}.${MINOR_VERSION}${PATCH_VERSION})
++
++add_definitions( -Wall -O3 -g -Wno-pointer-sign -fPIC )
++# add_definitions( -Wall -O0 -g -Wno-pointer-sign )
++
++### ORC is not used in any active code at the moment ###
+ # I tried it with 0.4.14
+ # 0.4.10 did not work (not all opcode implemented)
+-# find_package(Orc) // it actually not used by any active code
++# find_package(Orc)
+ if(ORC_FOUND)
+ add_definitions( -DUSE_ORC ${ORC_DEFINITIONS} )
+ include_directories( ${ORC_INCLUDE_DIRS} )
+@@ -20,15 +28,25 @@ endif()
+
+ # here we should check for SSE2
+ # our -DUSE_SSE2_ASM code does not work with fpic
+-add_definitions( -fPIC -DUSE_SSE2 -msse2 -ffast-math )
++if(SSE2_FOUND)
++add_definitions( -DUSE_SSE2 -msse2 -ffast-math )
++endif()
+
+-# Create the vidstab library
+-add_library (vidstab STATIC
+- frameinfo.c transformtype.c libvidstab.c transform.c transformfixedpoint.c
++set(SOURCES frameinfo.c transformtype.c libvidstab.c transform.c transformfixedpoint.c
+ motiondetect.c motiondetect_opt.c serialize.c
+- localmotion2transform.c
+- boxblur.c vsvector.c orc/motiondetectorc.c)
+-# orc/transformorc.c
++ localmotion2transform.c boxblur.c vsvector.c orc/motiondetectorc.c)
++
++set(HEADERS frameinfo.h transformtype.h libvidstab.h transform.h
++ motiondetect.h serialize.h localmotion2transform.h boxblur.h vsvector.h )
++
++
++# Create the vidstab library
++# add_library (vidstab STATIC ${SOURCES})
++add_library (vidstab SHARED ${SOURCES})
++
++#set version of lib
++set_target_properties(vidstab PROPERTIES SOVERSION ${MAJOR_VERSION}.${MINOR_VERSION})
++
+
+ target_link_libraries(vidstab m)
+ if(ORC_FOUND)
+@@ -37,3 +55,18 @@ endif()
+ if(USE_OMP)
+ target_link_libraries(vidstab gomp)
+ endif()
++
++
++#if(!NOHEADERS)
++FILE(GLOB HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
++INSTALL(FILES ${HEADERS} DESTINATION include/vid.stab)
++#endif()
++
++INSTALL(TARGETS vidstab
++ RUNTIME DESTINATION bin
++ LIBRARY DESTINATION lib
++ ARCHIVE DESTINATION lib
++)
++
++include(create_pkgconfig_file)
++create_pkgconfig_file(vidstab "Vid.Stab, a library for stabilizing video clips")
+diff --git a/src/boxblur.c b/src/boxblur.c
+index b7a1488..db376fe 100644
+--- a/src/boxblur.c
++++ b/src/boxblur.c
+@@ -27,9 +27,9 @@
+
+
+ void boxblur_hori_C(unsigned char* dest, const unsigned char* src,
+- int width, int height, int dest_strive, int src_strive, int size);
++ int width, int height, int dest_strive, int src_strive, int size);
+ void boxblur_vert_C(unsigned char* dest, const unsigned char* src,
+- int width, int height, int dest_strive, int src_strive, int size);
++ int width, int height, int dest_strive, int src_strive, int size);
+
+ /*
+ The algorithm:
+@@ -43,74 +43,74 @@ void boxblur_vert_C(unsigned char* dest, const unsigned char* src,
+ accumulator: acc = acc + new - old, pixel = acc/size
+ */
+
+-void boxblurYUV(VSFrame* dest, const VSFrame* src,
+- VSFrame* buffer, const VSFrameInfo* fi,
+- unsigned int size, BoxBlurColorMode colormode){
++void boxblurPlanar(VSFrame* dest, const VSFrame* src,
++ VSFrame* buffer, const VSFrameInfo* fi,
++ unsigned int size, BoxBlurColorMode colormode){
+ int localbuffer=0;
+ int size2;
+ if(size<2){
+ if(dest!=src)
+- copyFrame(dest,src,fi);
++ vsFrameCopy(dest,src,fi);
+ return;
+ }
+- VSFrame buf;
++ VSFrame buf;
+ if(buffer==0){
+- allocateFrame(&buf,fi);
+- localbuffer=1;
++ vsFrameAllocate(&buf,fi);
++ localbuffer=1;
+ }else{
+- buf = *buffer;
+- }
++ buf = *buffer;
++ }
+ // odd and larger than 2 and maximally half of smaller image dimension
+ size = VS_CLAMP((size/2)*2+1,3,VS_MIN(fi->height/2,fi->width/2));
+ //printf("%i\n",size);
+
+ // luminance
+ boxblur_hori_C(buf.data[0], src->data[0],
+- fi->width, fi->height, buf.linesize[0],src->linesize[0], size);
++ fi->width, fi->height, buf.linesize[0],src->linesize[0], size);
+ boxblur_vert_C(dest->data[0], buf.data[0],
+- fi->width, fi->height, dest->linesize[0], buf.linesize[0], size);
+-
+- size2 = size/2+1; // odd and larger than 0
+- int plane;
+- switch (colormode){
+- case BoxBlurColor:
+- // color
+- if(size2>1){
+- for(plane=1; plane<fi->planes; plane++){
+- boxblur_hori_C(buf.data[plane], src->data[plane],
+- fi->width >> getPlaneWidthSubS(fi,plane),
+- fi->height >> getPlaneHeightSubS(fi,plane),
+- buf.linesize[plane], src->linesize[plane], size2);
+- boxblur_vert_C(dest->data[plane], buf.data[plane],
+- fi->width >> getPlaneWidthSubS(fi,plane),
+- fi->height >> getPlaneHeightSubS(fi,plane),
+- dest->linesize[plane], buf.linesize[plane], size2);
+- }
+- }
+- break;
+- case BoxBlurKeepColor:
+- // copy both color channels
+- for(plane=1; plane<fi->planes; plane++){
+- copyFramePlane(dest, src, fi, plane);
+- }
+- case BoxBlurNoColor: // do nothing
+- default:
+- break;
+- }
++ fi->width, fi->height, dest->linesize[0], buf.linesize[0], size);
++
++ size2 = size/2+1; // odd and larger than 0
++ int plane;
++ switch (colormode){
++ case BoxBlurColor:
++ // color
++ if(size2>1){
++ for(plane=1; plane<fi->planes; plane++){
++ boxblur_hori_C(buf.data[plane], src->data[plane],
++ fi->width >> vsGetPlaneWidthSubS(fi,plane),
++ fi->height >> vsGetPlaneHeightSubS(fi,plane),
++ buf.linesize[plane], src->linesize[plane], size2);
++ boxblur_vert_C(dest->data[plane], buf.data[plane],
++ fi->width >> vsGetPlaneWidthSubS(fi,plane),
++ fi->height >> vsGetPlaneHeightSubS(fi,plane),
++ dest->linesize[plane], buf.linesize[plane], size2);
++ }
++ }
++ break;
++ case BoxBlurKeepColor:
++ // copy both color channels
++ for(plane=1; plane<fi->planes; plane++){
++ vsFrameCopyPlane(dest, src, fi, plane);
++ }
++ case BoxBlurNoColor: // do nothing
++ default:
++ break;
++ }
+
+ if(localbuffer)
+- freeFrame(&buf);
++ vsFrameFree(&buf);
+ }
+
+ /* /\* */
+ /* The algorithm: */
+-/* see boxblurYUV but here we for RGB */
++/* see boxblurPlanar but here we for Packed */
+
+ /* we add the 3 bytes of one pixel as if they where one number */
+ /* *\/ */
+-/* void boxblurRGB(const unsigned char* src, unsigned char* dest, */
+-/* unsigned char* buffer, const VSFrameInfo* fi, */
+-/* unsigned int size){ */
++/* void boxblurPacked(const unsigned char* src, unsigned char* dest, */
++/* unsigned char* buffer, const VSFrameInfo* fi, */
++/* unsigned int size){ */
+ /* int localbuffer=0; */
+ /* if(buffer==0){ */
+ /* buffer=(unsigned char*) vs_malloc(fi->framesize); */
+@@ -120,7 +120,7 @@ void boxblurYUV(VSFrame* dest, const VSFrame* src,
+ /* // (and not larger than 256, because otherwise we can get an overflow) */
+ /* size = VS_CLAMP((size/2)*2+1,3,VS_MIN(256,VS_MIN(fi->height/2,fi->width/2))); */
+
+-/* // we need a different version of these functions for RGB */
++/* // we need a different version of these functions for Packed */
+ /* boxblur_hori_C(src, buffer, fi->width, fi->height, fi->strive, size); */
+ /* boxblur_vert_C(buffer, dest, fi->width, fi->height, fi->strive, size); */
+
+@@ -130,7 +130,7 @@ void boxblurYUV(VSFrame* dest, const VSFrame* src,
+
+
+ void boxblur_hori_C(unsigned char* dest, const unsigned char* src,
+- int width, int height, int dest_strive, int src_strive, int size){
++ int width, int height, int dest_strive, int src_strive, int size){
+
+ int i,j,k;
+ unsigned int acc;
+@@ -160,7 +160,7 @@ void boxblur_hori_C(unsigned char* dest, const unsigned char* src,
+ }
+
+ void boxblur_vert_C(unsigned char* dest, const unsigned char* src,
+- int width, int height, int dest_strive, int src_strive, int size){
++ int width, int height, int dest_strive, int src_strive, int size){
+
+ int i,j,k;
+ int acc;
+diff --git a/src/boxblur.h b/src/boxblur.h
+index b341589..3f8fac0 100644
+--- a/src/boxblur.h
++++ b/src/boxblur.h
+@@ -39,8 +39,8 @@ typedef enum _BoxBlurColorMode { BoxBlurColor, BoxBlurKeepColor, BoxBlurNoColor}
+ * @param size of bluring kernel, (min 3 and it is made odd)
+ * @param onlyLumincance if true color planes stay untouched
+ */
+-void boxblurYUV(VSFrame* dest, const VSFrame* src,
+- VSFrame* buffer, const VSFrameInfo* fi,
+- unsigned int size, BoxBlurColorMode colormode);
++void boxblurPlanar(VSFrame* dest, const VSFrame* src,
++ VSFrame* buffer, const VSFrameInfo* fi,
++ unsigned int size, BoxBlurColorMode colormode);
+
+ #endif
+diff --git a/src/frameinfo.c b/src/frameinfo.c
+index 9580d74..36a2c44 100644
+--- a/src/frameinfo.c
++++ b/src/frameinfo.c
+@@ -25,8 +25,9 @@
+ #include "frameinfo.h"
+ #include "vidstabdefines.h"
+ #include <assert.h>
++#include <string.h>
+
+-int initFrameInfo(VSFrameInfo* fi, int width, int height, PixelFormat pFormat){
++int vsFrameInfoInit(VSFrameInfo* fi, int width, int height, VSPixelFormat pFormat){
+ fi->pFormat=pFormat;
+ fi->width = width;
+ fi->height = height;
+@@ -82,36 +83,36 @@ int initFrameInfo(VSFrameInfo* fi, int width, int height, PixelFormat pFormat){
+ return 1;
+ }
+
+-int getPlaneWidthSubS(const VSFrameInfo* fi, int plane){
+- return plane == 1 || plane == 2 ? fi->log2ChromaW : 0;
++int vsGetPlaneWidthSubS(const VSFrameInfo* fi, int plane){
++ return plane == 1 || plane == 2 ? fi->log2ChromaW : 0;
+ }
+
+-int getPlaneHeightSubS(const VSFrameInfo* fi, int plane){
+- return plane == 1 || plane == 2 ? fi->log2ChromaH : 0;
++int vsGetPlaneHeightSubS(const VSFrameInfo* fi, int plane){
++ return plane == 1 || plane == 2 ? fi->log2ChromaH : 0;
+ }
+
+-int isNullFrame(const VSFrame* frame) {
+- return frame==0 || frame->data[0]==0;
++int vsFrameIsNull(const VSFrame* frame) {
++ return frame==0 || frame->data[0]==0;
+ }
+
+
+-int equalFrames(const VSFrame* frame1,const VSFrame* frame2){
+- return frame1 && frame2 && (frame1==frame2 || frame1->data[0] == frame2->data[0]);
++int vsFramesEqual(const VSFrame* frame1,const VSFrame* frame2){
++ return frame1 && frame2 && (frame1==frame2 || frame1->data[0] == frame2->data[0]);
+ }
+
+-void nullFrame(VSFrame* frame){
+- memset(frame->data,0,sizeof(uint8_t*)*4);
+- memset(frame->linesize,0,sizeof(int)*4);
++void vsFrameNull(VSFrame* frame){
++ memset(frame->data,0,sizeof(uint8_t*)*4);
++ memset(frame->linesize,0,sizeof(int)*4);
+ }
+
+-void allocateFrame(VSFrame* frame, const VSFrameInfo* fi){
+- nullFrame(frame);
++void vsFrameAllocate(VSFrame* frame, const VSFrameInfo* fi){
++ vsFrameNull(frame);
+ if(fi->pFormat<PF_PACKED){
+ int i;
+ assert(fi->planes > 0 && fi->planes <= 4);
+ for (i=0; i< fi->planes; i++){
+- int w = fi->width >> getPlaneWidthSubS(fi, i);
+- int h = fi->height >> getPlaneHeightSubS(fi, i);
++ int w = fi->width >> vsGetPlaneWidthSubS(fi, i);
++ int h = fi->height >> vsGetPlaneHeightSubS(fi, i);
+ frame->data[i] = vs_zalloc(w * h * sizeof(uint8_t));
+ frame->linesize[i] = w;
+ if(frame->data[i]==0)
+@@ -128,53 +129,53 @@ void allocateFrame(VSFrame* frame, const VSFrameInfo* fi){
+ }
+ }
+
+-void copyFramePlane(VSFrame* dest, const VSFrame* src,
+- const VSFrameInfo* fi, int plane){
+- assert(src->data[plane]);
+- int h = fi->height >> getPlaneHeightSubS(fi, plane);
+- if(src->linesize[plane] == dest->linesize[plane])
+- memcpy(dest->data[plane], src->data[plane], src->linesize[plane] * h * sizeof(uint8_t));
+- else {
+- uint8_t* d = dest->data[plane];
+- const uint8_t* s = src->data[plane];
+- int w = fi->width >> getPlaneWidthSubS(fi, plane);
+- for (; h>0; h++) {
+- memcpy(d,s,sizeof(uint8_t) * w);
+- d += dest->linesize[plane];
+- s += src ->linesize[plane];
+- }
+- }
++void vsFrameCopyPlane(VSFrame* dest, const VSFrame* src,
++ const VSFrameInfo* fi, int plane){
++ assert(src->data[plane]);
++ int h = fi->height >> vsGetPlaneHeightSubS(fi, plane);
++ if(src->linesize[plane] == dest->linesize[plane])
++ memcpy(dest->data[plane], src->data[plane], src->linesize[plane] * h * sizeof(uint8_t));
++ else {
++ uint8_t* d = dest->data[plane];
++ const uint8_t* s = src->data[plane];
++ int w = fi->width >> vsGetPlaneWidthSubS(fi, plane);
++ for (; h>0; h--) {
++ memcpy(d,s,sizeof(uint8_t) * w);
++ d += dest->linesize[plane];
++ s += src ->linesize[plane];
++ }
++ }
+ }
+
+-void copyFrame(VSFrame* dest, const VSFrame* src, const VSFrameInfo* fi){
+- int plane;
+- assert(fi->planes > 0 && fi->planes <= 4);
+- for (plane=0; plane< fi->planes; plane++){
+- copyFramePlane(dest,src,fi,plane);
+- }
++void vsFrameCopy(VSFrame* dest, const VSFrame* src, const VSFrameInfo* fi){
++ int plane;
++ assert(fi->planes > 0 && fi->planes <= 4);
++ for (plane=0; plane< fi->planes; plane++){
++ vsFrameCopyPlane(dest,src,fi,plane);
++ }
+ }
+
+-void fillFrameFromBuffer(VSFrame* frame, uint8_t* img, const VSFrameInfo* fi){
++void vsFrameFillFromBuffer(VSFrame* frame, uint8_t* img, const VSFrameInfo* fi){
+ assert(fi->planes > 0 && fi->planes <= 4);
+- nullFrame(frame);
++ vsFrameNull(frame);
+ long int offset = 0;
+ int i;
+ for (i=0; i< fi->planes; i++){
+- int w = fi->width >> getPlaneWidthSubS(fi, i);
+- int h = fi->height >> getPlaneHeightSubS(fi, i);
++ int w = fi->width >> vsGetPlaneWidthSubS(fi, i);
++ int h = fi->height >> vsGetPlaneHeightSubS(fi, i);
+ frame->data[i] = img + offset;
+ frame->linesize[i] = w*fi->bytesPerPixel;
+ offset += h * w*fi->bytesPerPixel;
+ }
+ }
+
+-void freeFrame(VSFrame* frame){
+- int plane;
+- for (plane=0; plane< 4; plane++){
+- if(frame->data[plane]) vs_free(frame->data[plane]);
+- frame->data[plane]=0;
+- frame->linesize[plane]=0;
+- }
++void vsFrameFree(VSFrame* frame){
++ int plane;
++ for (plane=0; plane< 4; plane++){
++ if(frame->data[plane]) vs_free(frame->data[plane]);
++ frame->data[plane]=0;
++ frame->linesize[plane]=0;
++ }
+ }
+
+
+diff --git a/src/frameinfo.h b/src/frameinfo.h
+index 76a2d61..f48e92e 100644
+--- a/src/frameinfo.h
++++ b/src/frameinfo.h
+@@ -43,7 +43,7 @@ typedef enum {PF_NONE = -1,
+ PF_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
+ PF_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
+ PF_NUMBER ///< number of pixel formats
+-} PixelFormat;
++} VSPixelFormat;
+
+ /** frame information for deshaking lib
+ This only works for planar image formats
+@@ -53,7 +53,7 @@ typedef struct vsframeinfo {
+ int planes; // number of planes (1 luma, 2,3 chroma, 4 alpha)
+ int log2ChromaW; // subsampling of width in chroma planes
+ int log2ChromaH; // subsampling of height in chroma planes
+- PixelFormat pFormat;
++ VSPixelFormat pFormat;
+ int bytesPerPixel; // number of bytes per pixel (for packed formats)
+ } VSFrameInfo;
+
+@@ -68,43 +68,43 @@ typedef struct vsframe {
+ #define CHROMA_SIZE(width,log2sub) (-(-(width) >> (log2sub)))
+
+ /// initializes the frameinfo for the given format
+-int initFrameInfo(VSFrameInfo* fi, int width, int height, PixelFormat pFormat);
++int vsFrameInfoInit(VSFrameInfo* fi, int width, int height, VSPixelFormat pFormat);
+
+
+ /// returns the subsampling shift amount, horizonatally for the given plane
+-int getPlaneWidthSubS(const VSFrameInfo* fi, int plane);
++int vsGetPlaneWidthSubS(const VSFrameInfo* fi, int plane);
+
+ /// returns the subsampling shift amount, vertically for the given plane
+-int getPlaneHeightSubS(const VSFrameInfo* fi, int plane);
++int vsGetPlaneHeightSubS(const VSFrameInfo* fi, int plane);
+
+ /// zero initialization
+-void nullFrame(VSFrame* frame);
++void vsFrameNull(VSFrame* frame);
+
+ /// returns true if frame is null (data[0]==0)
+-int isNullFrame(const VSFrame* frame);
++int vsFrameIsNull(const VSFrame* frame);
+
+ /// compares two frames for identity (based in data[0])
+-int equalFrames(const VSFrame* frame1,const VSFrame* frame2);
++int vsFramesEqual(const VSFrame* frame1,const VSFrame* frame2);
+
+ /// allocates memory for a frame
+-void allocateFrame(VSFrame* frame, const VSFrameInfo* fi);
++void vsFrameAllocate(VSFrame* frame, const VSFrameInfo* fi);
+
+
+ /// copies the given plane number from src to dest
+-void copyFramePlane(VSFrame* dest, const VSFrame* src,
+- const VSFrameInfo* fi, int plane);
++void vsFrameCopyPlane(VSFrame* dest, const VSFrame* src,
++ const VSFrameInfo* fi, int plane);
+
+ /// copies src to dest
+-void copyFrame(VSFrame* dest, const VSFrame* src, const VSFrameInfo* fi);
++void vsFrameCopy(VSFrame* dest, const VSFrame* src, const VSFrameInfo* fi);
+
+ /** fills the data pointer so that it corresponds to the img saved in the linear buffer.
+ No copying is performed.
+- Do not call freeFrame() on it.
++ Do not call vsFrameFree() on it.
+ */
+-void fillFrameFromBuffer(VSFrame* frame, uint8_t* img, const VSFrameInfo* fi);
++void vsFrameFillFromBuffer(VSFrame* frame, uint8_t* img, const VSFrameInfo* fi);
+
+ /// frees memory
+-void freeFrame(VSFrame* frame);
++void vsFrameFree(VSFrame* frame);
+
+ #endif /* FRAMEINFO_H */
+
+diff --git a/src/libvidstab.c b/src/libvidstab.c
+index b804f3a..263093b 100644
+--- a/src/libvidstab.c
++++ b/src/libvidstab.c
+@@ -24,6 +24,50 @@
+
+ #include "libvidstab.h"
+
++#include <string.h>
++#include <stdio.h>
++#include <stdarg.h>
++
++/**** default values for memory and logging ****/
++
++/// memory allocation with zero initialization
++void* _zalloc(size_t size){
++ return memset(malloc(size),0,size);
++}
++
++/// logging function
++int _vs_log(int type, const char* tag, const char* format, ...){
++ fprintf(stderr,"%s (%s):",
++ type == VS_ERROR_TYPE ? "Error: " :
++ type == VS_WARN_TYPE ? "Warn: " :
++ type == VS_INFO_TYPE ? "Info: " :
++ type == VS_MSG_TYPE ? "Msg: " : "Unknown",
++ tag);
++ va_list ap;
++ va_start (ap, format);
++ vfprintf (stderr, format, ap);
++ va_end (ap);
++ fprintf(stderr,"\n");
++ return 0;
++}
++
++
++vs_malloc_t vs_malloc = malloc;
++vs_realloc_t vs_realloc = realloc;
++vs_free_t vs_free = free;
++vs_zalloc_t vs_zalloc = _zalloc;
++
++vs_strdup_t vs_strdup = strdup;
++vs_strndup_t vs_strndup = strndup;
++
++vs_log_t vs_log = _vs_log;
++int VS_ERROR_TYPE = 0;
++int VS_WARN_TYPE = 1;
++int VS_INFO_TYPE = 2;
++int VS_MSG_TYPE = 3;
++
++int VS_ERROR = -1;
++int VS_OK = 0;
+
+ /*
+ * Local variables:
+diff --git a/src/libvidstab.h b/src/libvidstab.h
+index 88d960f..8debdf0 100644
+--- a/src/libvidstab.h
++++ b/src/libvidstab.h
+@@ -25,21 +25,15 @@
+ #ifndef LIBVIDSTAB_H
+ #define LIBVIDSTAB_H
+
+-#define LIBVIDSTAB_VERSION "v0.96 (2013-02-19)"
++#define LIBVIDSTAB_VERSION "v0.961 (2013-04-16)"
+
+ #include "frameinfo.h"
+ #include "motiondetect.h"
+ #include "transform.h"
+-#include "boxblur.h"
+ #include "vsvector.h"
+ #include "serialize.h"
+ #include "localmotion2transform.h"
+
+-#include "transformfixedpoint.h"
+-#ifdef TESTING
+-#include "transformfloat.h"
+-#endif
+-
+ #endif /* LIBVIDSTAB_H_ */
+
+ /*
+@@ -47,6 +41,8 @@
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
++ * c-basic-offset: 2 t
+ * End:
+ *
++ * vim: expandtab shiftwidth=2:
+ */
+diff --git a/src/localmotion2transform.c b/src/localmotion2transform.c
+index 601e1ad..4637235 100644
+--- a/src/localmotion2transform.c
++++ b/src/localmotion2transform.c
+@@ -23,29 +23,30 @@
+ */
+
+ #include "localmotion2transform.h"
++#include "transformtype_operations.h"
+ #include <assert.h>
+
+-int localmotions2TransformsSimple(TransformData* td,
+- const ManyLocalMotions* motions,
+- Transformations* trans ){
+- int i;
+- int len = vs_vector_size(motions);
+- assert(trans->len==0 && trans->ts == 0);
+- trans->ts = vs_malloc(sizeof(Transform)*len );
+- for(i=0; i< vs_vector_size(motions); i++) {
+- trans->ts[i]=simpleMotionsToTransform(td,MLMGet(motions,i));
+- // storeLocalmotions(stderr,MLMGet(motions,i));
+- // storeTransform(stderr,&trans->ts[i]);
+- }
+- trans->len=len;
+- return VS_OK;
++int vsLocalmotions2TransformsSimple(VSTransformData* td,
++ const VSManyLocalMotions* motions,
++ VSTransformations* trans ){
++ int i;
++ int len = vs_vector_size(motions);
++ assert(trans->len==0 && trans->ts == 0);
++ trans->ts = vs_malloc(sizeof(VSTransform)*len );
++ for(i=0; i< vs_vector_size(motions); i++) {
++ trans->ts[i]=vsSimpleMotionsToTransform(td,VSMLMGet(motions,i));
++ // vsStoreLocalmotions(stderr,VSMLMGet(motions,i));
++ // storeTransform(stderr,&trans->ts[i]);
++ }
++ trans->len=len;
++ return VS_OK;
+ }
+
+
+ /* calculates rotation angle for the given transform and
+ * field with respect to the given center-point
+ */
+-double calcAngle(const LocalMotion* lm, int center_x, int center_y){
++double vsCalcAngle(const LocalMotion* lm, int center_x, int center_y){
+ // we better ignore fields that are to close to the rotation center
+ if (abs(lm->f.x - center_x) + abs(lm->f.y - center_y) < lm->f.size*2) {
+ return 0;
+@@ -56,16 +57,16 @@ double calcAngle(const LocalMotion* lm, int center_x, int center_y){
+ lm->f.x - center_x + lm->v.x);
+ double diff = a2 - a1;
+ return (diff > M_PI) ? diff - 2 * M_PI : ((diff < -M_PI) ? diff + 2
+- * M_PI : diff);
++ * M_PI : diff);
+ }
+ }
+
+
+-Transform simpleMotionsToTransform(TransformData* td,
++VSTransform vsSimpleMotionsToTransform(VSTransformData* td,
+ const LocalMotions* motions){
+ int center_x = 0;
+ int center_y = 0;
+- Transform t = null_transform();
++ VSTransform t = null_transform();
+ if(motions==0) return t;
+ int num_motions=vs_vector_size(motions);
+ double *angles = (double*) vs_malloc(sizeof(double) * num_motions);
+@@ -93,14 +94,14 @@ Transform simpleMotionsToTransform(TransformData* td,
+ for (i = 0; i < num_motions; i++) {
+ // substract avg and calc angle
+ LocalMotion m = sub_localmotion(LMGet(motions,i),&meanmotion);
+- angles[i] = calcAngle(&m, center_x, center_y);
++ angles[i] = vsCalcAngle(&m, center_x, center_y);
+ }
+ double min, max;
+ t.alpha = -cleanmean(angles, num_motions, &min, &max);
+ if (max - min > td->maxAngleVariation) {
+ t.alpha = 0;
+- vs_log_info(td->modName, "too large variation in angle(%f)\n",
+- max-min);
++ vs_log_info(td->conf.modName, "too large variation in angle(%f)\n",
++ max-min);
+ }
+ }
+ vs_free(angles);
+diff --git a/src/localmotion2transform.h b/src/localmotion2transform.h
+index cd6b173..6a41e30 100644
+--- a/src/localmotion2transform.h
++++ b/src/localmotion2transform.h
+@@ -33,21 +33,21 @@
+
+ /** converts for each frame the localmotions into a transform
+ */
+-int localmotions2TransformsSimple(TransformData* td,
+- const ManyLocalMotions* motions,
+- Transformations* trans );
++int vsLocalmotions2TransformsSimple(VSTransformData* td,
++ const VSManyLocalMotions* motions,
++ VSTransformations* trans );
+
+
+ /** calculates rotation angle for the given transform and
+ * field with respect to the given center-point
+ */
+-double calcAngle(const LocalMotion* lm, int center_x, int center_y);
++double vsCalcAngle(const LocalMotion* lm, int center_x, int center_y);
+
+ /** calculates the transformation that caused the observed motions.
+ Using a simple cleaned-means approach to eliminate outliers.
+ translation and rotation is calculated.
+ */
+-Transform simpleMotionsToTransform(TransformData* td,
++VSTransform vsSimpleMotionsToTransform(VSTransformData* td,
+ const LocalMotions* motions);
+
+ #endif
+diff --git a/src/motiondetect.c b/src/motiondetect.c
+index 749a93e..921230a 100644
+--- a/src/motiondetect.c
++++ b/src/motiondetect.c
+@@ -25,6 +25,7 @@
+ *
+ */
+ #include "motiondetect.h"
++#include "motiondetect_internal.h"
+ #include "motiondetect_opt.h"
+ #include <math.h>
+ #include <limits.h>
+@@ -39,6 +40,10 @@
+ #include "boxblur.h"
+ #include "vidstabdefines.h"
+ #include "localmotion2transform.h"
++#include "transformtype_operations.h"
++
++#define USE_SPIRAL_FIELD_CALC
++
+
+ /* internal data structures */
+
+@@ -48,104 +53,111 @@ typedef struct _contrast_idx {
+ int index;
+ } contrast_idx;
+
+-int initMotionDetect(MotionDetect* md, const VSFrameInfo* fi,
+- const char* modName) {
++
++VSMotionDetectConfig vsMotionDetectGetDefaulfConfig(const char* modName){
++ VSMotionDetectConfig conf;
++ conf.stepSize = 6;
++ conf.algo = 1;
++ conf.accuracy = 9;
++ conf.shakiness = 5;
++ conf.virtualTripod = 0;
++ conf.contrastThreshold = 0.25;
++ conf.show = 0;
++ conf.modName = modName;
++ return conf;
++}
++
++void vsMotionDetectGetConfig(VSMotionDetectConfig* conf, const VSMotionDetect* md){
++ if(md && conf)
++ *conf = md->conf;
++}
++
++const VSFrameInfo* vsMotionDetectGetFrameInfo(const VSMotionDetect* md){
++ return &md->fi;
++}
++
++
++int vsMotionDetectInit(VSMotionDetect* md, const VSMotionDetectConfig* conf, const VSFrameInfo* fi){
+ assert(md && fi);
++ md->conf = *conf;
+ md->fi = *fi;
+- md->modName = modName;
+
+ if(fi->pFormat<=PF_NONE || fi->pFormat==PF_PACKED || fi->pFormat>=PF_NUMBER) {
+- vs_log_warn(md->modName, "unsupported Pixel Format (%i)\n",
++ vs_log_warn(md->conf.modName, "unsupported Pixel Format (%i)\n",
+ md->fi.pFormat);
+ return VS_ERROR;
+ }
+
+- allocateFrame(&md->prev, &md->fi);
+- if (isNullFrame(&md->prev)) {
+- vs_log_error(md->modName, "malloc failed");
++ vsFrameAllocate(&md->prev, &md->fi);
++ if (vsFrameIsNull(&md->prev)) {
++ vs_log_error(md->conf.modName, "malloc failed");
+ return VS_ERROR;
+ }
+
+- nullFrame(&md->curr);
+- nullFrame(&md->currorig);
+- nullFrame(&md->currtmp);
++ vsFrameNull(&md->curr);
++ vsFrameNull(&md->currorig);
++ vsFrameNull(&md->currtmp);
+ md->hasSeenOneFrame = 0;
+ md->frameNum = 0;
+
+- // Options
+- md->stepSize = 6;
+- md->allowMax = 0;
+- md->algo = 1;
+- md->accuracy = 9;
+- md->shakiness = 5;
+ md->fieldSize = VS_MIN(md->fi.width, md->fi.height) / 12;
+- md->virtualTripod = 0;
+- md->show = 0;
+- md->contrastThreshold = 0.25;
+- md->initialized = 1;
+- return VS_OK;
+-}
+-
+-int configureMotionDetect(MotionDetect* md) {
+- if (md->initialized != 1)
+- return VS_ERROR;
++ md->allowMax = 0;
++ md->fieldNum = 0; // will be set in initFields()
+
+- md->shakiness = VS_MIN(10,VS_MAX(1,md->shakiness));
+- md->accuracy = VS_MIN(15,VS_MAX(1,md->accuracy));
+- if (md->accuracy < md->shakiness / 2) {
+- vs_log_info(md->modName, "Accuracy should not be lower than shakiness/2 -- fixed");
+- md->accuracy = md->shakiness / 2;
++ md->conf.shakiness = VS_MIN(10,VS_MAX(1,md->conf.shakiness));
++ md->conf.accuracy = VS_MIN(15,VS_MAX(1,md->conf.accuracy));
++ if (md->conf.accuracy < md->conf.shakiness / 2) {
++ vs_log_info(md->conf.modName, "Accuracy should not be lower than shakiness/2 -- fixed");
++ md->conf.accuracy = md->conf.shakiness / 2;
+ }
+- if (md->accuracy > 9 && md->stepSize > 6) {
+- vs_log_info(md->modName, "For high accuracy use lower stepsize -- set to 6 now");
+- md->stepSize = 6; // maybe 4
++ if (md->conf.accuracy > 9 && md->conf.stepSize > 6) {
++ vs_log_info(md->conf.modName, "For high accuracy use lower stepsize -- set to 6 now");
++ md->conf.stepSize = 6; // maybe 4
+ }
+
+ // shift: shakiness 1: height/40; 10: height/4
+ int minDimension = VS_MIN(md->fi.width, md->fi.height);
+- md->maxShift
+- = VS_MAX(4,(minDimension*md->shakiness)/40);
++ md->maxShift = VS_MAX(4,(minDimension*md->conf.shakiness)/40);
+ // size: shakiness 1: height/40; 10: height/6 (clipped)
+- md->fieldSize
+- = VS_MAX(4,VS_MIN(minDimension/6, (minDimension*md->shakiness)/40));
++ md->fieldSize = VS_MAX(4,VS_MIN(minDimension/6, (minDimension*md->conf.shakiness)/40));
+
+ #if defined(USE_SSE2) || defined(USE_SSE2_ASM)
+ md->fieldSize = (md->fieldSize / 16 + 1) * 16;
+ #endif
+
+- vs_log_info(md->modName, "Fieldsize: %i, Maximal translation: %i pixel",
+- md->fieldSize, md->maxShift);
+- if (md->algo == 1) {
++ vs_log_info(md->conf.modName, "Fieldsize: %i, Maximal translation: %i pixel\n",
++ md->fieldSize, md->maxShift);
++ if (md->conf.algo == 1) {
+ // initialize measurement fields. field_num is set here.
+ if (!initFields(md)) {
+ return VS_ERROR;
+ }
+- md->maxFields = (md->accuracy) * md->fieldNum / 15;
+- vs_log_info(md->modName, "Number of used measurement fields: %i out of %i",
+- md->maxFields, md->fieldNum);
++ md->maxFields = (md->conf.accuracy) * md->fieldNum / 15;
++ vs_log_info(md->conf.modName, "Number of used measurement fields: %i out of %i\n",
++ md->maxFields, md->fieldNum);
+ }
+ // if (md->show)
+- allocateFrame(&md->curr,&md->fi);
+- allocateFrame(&md->currtmp, &md->fi);
++ vsFrameAllocate(&md->curr,&md->fi);
++ vsFrameAllocate(&md->currtmp, &md->fi);
+
+ md->initialized = 2;
+ return VS_OK;
+ }
+
+-void cleanupMotionDetection(MotionDetect* md) {
++void vsMotionDetectionCleanup(VSMotionDetect* md) {
+ if(md->fields) {
+ vs_free(md->fields);
+ md->fields=0;
+ }
+- freeFrame(&md->prev);
+- freeFrame(&md->curr);
+- freeFrame(&md->currtmp);
++ vsFrameFree(&md->prev);
++ vsFrameFree(&md->curr);
++ vsFrameFree(&md->currtmp);
+
+ md->initialized = 0;
+ }
+
+
+-int motionDetection(MotionDetect* md, LocalMotions* motions, VSFrame *frame) {
++int vsMotionDetection(VSMotionDetect* md, LocalMotions* motions, VSFrame *frame) {
+ assert(md->initialized==2);
+
+ md->currorig = *frame;
+@@ -154,38 +166,38 @@ int motionDetection(MotionDetect* md, LocalMotions* motions, VSFrame *frame) {
+ if (md->fi.pFormat > PF_PACKED) {
+ // we could calculate a grayscale version and use the PLANAR stuff afterwards
+ // so far smoothing is only implemented for PLANAR
+- copyFrame(&md->curr, frame, &md->fi);
++ vsFrameCopy(&md->curr, frame, &md->fi);
+ } else {
+ // box-kernel smoothing (plain average of pixels), which is fine for us
+- boxblurYUV(&md->curr, frame, &md->currtmp, &md->fi, md->stepSize*1/*1.4*/,
++ boxblurPlanar(&md->curr, frame, &md->currtmp, &md->fi, md->conf.stepSize*1/*1.4*/,
+ BoxBlurNoColor);
+ // two times yields tent-kernel smoothing, which may be better, but I don't
+ // think we need it
+- //boxblurYUV(md->curr, md->curr, md->currtmp, &md->fi, md->stepSize*1,
++ //boxblurPlanar(md->curr, md->curr, md->currtmp, &md->fi, md->stepSize*1,
+ // BoxBlurNoColor);
+ }
+
+ if (md->hasSeenOneFrame) {
+ // md->curr = frame;
+ if (md->fi.pFormat > PF_PACKED) {
+- if (md->algo == 0)
+- *motions = calcShiftRGBSimple(md);
+- else if (md->algo == 1)
+- *motions = calcTransFields(md, calcFieldTransRGB, contrastSubImgRGB);
++ if (md->conf.algo == 0)
++ *motions = calcShiftPackedSimple(md);
++ else if (md->conf.algo == 1)
++ *motions = calcTransFields(md, calcFieldTransPacked, contrastSubImgPacked);
+ } else { // PLANAR
+- if (md->algo == 0)
+- *motions = calcShiftYUVSimple(md);
+- else if (md->algo == 1)
+- *motions = calcTransFields(md, calcFieldTransYUV, contrastSubImgYUV);
++ if (md->conf.algo == 0)
++ *motions = calcShiftPlanarSimple(md);
++ else if (md->conf.algo == 1)
++ *motions = calcTransFields(md, calcFieldTransPlanar, contrastSubImgPlanar);
+ }
+ } else {
+ vs_vector_init(motions,md->maxFields);
+ md->hasSeenOneFrame = 1;
+ }
+
+- if(md->virtualTripod < 1 || md->frameNum < md->virtualTripod)
+- // copy current frame (smoothed) to prev for next frame comparison
+- copyFrame(&md->prev, &md->curr, &md->fi);
++ if(md->conf.virtualTripod < 1 || md->frameNum < md->conf.virtualTripod)
++ // copy current frame (smoothed) to prev for next frame comparison
++ vsFrameCopy(&md->prev, &md->curr, &md->fi);
+ md->frameNum++;
+ return VS_OK;
+ }
+@@ -195,7 +207,7 @@ int motionDetection(MotionDetect* md, LocalMotions* motions, VSFrame *frame) {
+ The size of the fields and the maxshift is used to
+ calculate an optimal distribution in the frame.
+ */
+-int initFields(MotionDetect* md) {
++int initFields(VSMotionDetect* md) {
+ int size = md->fieldSize;
+ int rows = VS_MAX(3,(md->fi.height - md->maxShift*2)/size-1);
+ int cols = VS_MAX(3,(md->fi.width - md->maxShift*2)/size-1);
+@@ -206,14 +218,14 @@ int initFields(MotionDetect* md) {
+ // rows, cols, md->field_num);
+
+ if (!(md->fields = (Field*) vs_malloc(sizeof(Field) * md->fieldNum))) {
+- vs_log_error(md->modName, "malloc failed!\n");
++ vs_log_error(md->conf.modName, "malloc failed!\n");
+ return 0;
+ } else {
+ int i, j;
+ // the border is the amount by which the field centers
+ // have to be away from the image boundary
+ // (stepsize is added in case shift is increased through stepsize)
+- int border = size / 2 + md->maxShift + md->stepSize;
++ int border = size / 2 + md->maxShift + md->conf.stepSize;
+ int step_x = (md->fi.width - 2 * border) / VS_MAX(cols-1,1);
+ int step_y = (md->fi.height - 2 * border) / VS_MAX(rows-1,1);
+ for (j = 0; j < rows; j++) {
+@@ -289,7 +301,7 @@ unsigned int compareImg(unsigned char* I1, unsigned char* I2, int width, int hei
+
+
+ /** \see contrastSubImg*/
+-double contrastSubImgYUV(MotionDetect* md, const Field* field) {
++double contrastSubImgPlanar(VSMotionDetect* md, const Field* field) {
+ #ifdef USE_SSE2
+ return contrastSubImg1_SSE(md->curr.data[0], field, md->curr.linesize[0],md->fi.height);
+ #else
+@@ -302,7 +314,7 @@ double contrastSubImgYUV(MotionDetect* md, const Field* field) {
+ \see contrastSubImg_Michelson three times called with bytesPerPixel=3
+ for all channels
+ */
+-double contrastSubImgRGB(MotionDetect* md, const Field* field) {
++double contrastSubImgPacked(VSMotionDetect* md, const Field* field) {
+ unsigned char* const I = md->curr.data[0];
+ int linesize2 = md->curr.linesize[0]/3; // linesize in pixels
+ return (contrastSubImg(I, field, linesize2, md->fi.height, 3)
+@@ -346,7 +358,7 @@ double contrastSubImg(unsigned char* const I, const Field* field, int width,
+ shift images to all possible positions and calc summed error
+ Shift with minimal error is selected.
+ */
+-LocalMotions calcShiftRGBSimple(MotionDetect* md) {
++LocalMotions calcShiftPackedSimple(VSMotionDetect* md) {
+ LocalMotions localmotions;
+ vs_vector_init(&localmotions,1);
+ LocalMotion lm;
+@@ -380,7 +392,7 @@ LocalMotions calcShiftRGBSimple(MotionDetect* md) {
+ shift images to all possible positions and calc summed error
+ Shift with minimal error is selected.
+ */
+-LocalMotions calcShiftYUVSimple(MotionDetect* md) {
++LocalMotions calcShiftPlanarSimple(VSMotionDetect* md) {
+ LocalMotions localmotions;
+ vs_vector_init(&localmotions,1);
+ LocalMotion lm;
+@@ -424,17 +436,17 @@ LocalMotions calcShiftYUVSimple(MotionDetect* md) {
+ return localmotions;
+ }
+
+-/* calculates the optimal transformation for one field in YUV frames
++/* calculates the optimal transformation for one field in Planar frames
+ * (only luminance)
+ */
+-LocalMotion calcFieldTransYUV(MotionDetect* md, const Field* field, int fieldnum) {
++LocalMotion calcFieldTransPlanar(VSMotionDetect* md, const Field* field, int fieldnum) {
+ int tx = 0;
+ int ty = 0;
+ uint8_t *Y_c = md->curr.data[0], *Y_p = md->prev.data[0];
+ int linesize_c = md->curr.linesize[0], linesize_p = md->prev.linesize[0];
+ // we only use the luminance part of the image
+ int i, j;
+- int stepSize = md->stepSize;
++ int stepSize = md->conf.stepSize;
+
+ #ifdef STABVERBOSE
+ // printf("%i %i %f\n", md->frameNum, fieldnum, contr);
+@@ -552,13 +564,13 @@ LocalMotion calcFieldTransYUV(MotionDetect* md, const Field* field, int fieldnum
+ vs_log_msg(md->modName, "Minerror: %f\n", minerror);
+ #endif
+
+- if (!md->allowMax && fabs(tx) >= md->maxShift + md->stepSize) {
++ if (!md->allowMax && fabs(tx) >= md->maxShift + md->conf.stepSize) {
+ #ifdef STABVERBOSE
+ vs_log_msg(md->modName, "maximal x shift ");
+ #endif
+ tx = 0;
+ }
+- if (!md->allowMax && fabs(ty) == md->maxShift + md->stepSize) {
++ if (!md->allowMax && fabs(ty) == md->maxShift + md->conf.stepSize) {
+ #ifdef STABVERBOSE
+ vs_log_msg(md->modName, "maximal y shift ");
+ #endif
+@@ -572,10 +584,10 @@ LocalMotion calcFieldTransYUV(MotionDetect* md, const Field* field, int fieldnum
+ return lm;
+ }
+
+-/* calculates the optimal transformation for one field in RGB
+- * slower than the YUV version because it uses all three color channels
++/* calculates the optimal transformation for one field in Packed
++ * slower than the Planar version because it uses all three color channels
+ */
+-LocalMotion calcFieldTransRGB(MotionDetect* md, const Field* field,
++LocalMotion calcFieldTransPacked(VSMotionDetect* md, const Field* field,
+ int fieldnum) {
+ int tx = 0;
+ int ty = 0;
+@@ -583,6 +595,7 @@ LocalMotion calcFieldTransRGB(MotionDetect* md, const Field* field,
+ int width1 = md->curr.linesize[0]/3; // linesize in pixels
+ int width2 = md->prev.linesize[0]/3; // linesize in pixels
+ int i, j;
++ int stepSize = md->conf.stepSize;
+
+ /* Here we improve speed by checking first the most probable position
+ then the search paths are most effectively cut. (0,0) is a simple start
+@@ -590,8 +603,8 @@ LocalMotion calcFieldTransRGB(MotionDetect* md, const Field* field,
+ unsigned int minerror = compareSubImg(I_c, I_p, field, width1, width2, md->fi.height,
+ 3, 0, 0, UINT_MAX);
+ // check all positions...
+- for (i = -md->maxShift; i <= md->maxShift; i += md->stepSize) {
+- for (j = -md->maxShift; j <= md->maxShift; j += md->stepSize) {
++ for (i = -md->maxShift; i <= md->maxShift; i += stepSize) {
++ for (j = -md->maxShift; j <= md->maxShift; j += stepSize) {
+ if( i==0 && j==0 )
+ continue; //no need to check this since already done
+ unsigned int error = compareSubImg(I_c, I_p, field, width1, width2,
+@@ -603,10 +616,10 @@ LocalMotion calcFieldTransRGB(MotionDetect* md, const Field* field,
+ }
+ }
+ }
+- if (md->stepSize > 1) { // make fine grain check around the best match
++ if (stepSize > 1) { // make fine grain check around the best match
+ int txc = tx; // save the shifts
+ int tyc = ty;
+- int r = md->stepSize - 1;
++ int r = stepSize - 1;
+ for (i = txc - r; i <= txc + r; i += 1) {
+ for (j = tyc - r; j <= tyc + r; j += 1) {
+ if (i == txc && j == tyc)
+@@ -622,13 +635,13 @@ LocalMotion calcFieldTransRGB(MotionDetect* md, const Field* field,
+ }
+ }
+
+- if (!md->allowMax && fabs(tx) >= md->maxShift + md->stepSize) {
++ if (!md->allowMax && fabs(tx) >= md->maxShift + stepSize - 1) {
+ #ifdef STABVERBOSE
+ vs_log_msg(md->modName, "maximal x shift ");
+ #endif
+ tx = 0;
+ }
+- if (!md->allowMax && fabs(ty) == md->maxShift + md->stepSize) {
++ if (!md->allowMax && fabs(ty) >= md->maxShift + stepSize - 1) {
+ #ifdef STABVERBOSE
+ vs_log_msg(md->modName, "maximal y shift ");
+ #endif
+@@ -655,7 +668,7 @@ int cmp_contrast_idx(const void *ci1, const void* ci2) {
+ first calc contrasts then select from each part of the
+ frame a some fields
+ */
+-VSVector selectfields(MotionDetect* md, contrastSubImgFunc contrastfunc) {
++VSVector selectfields(VSMotionDetect* md, contrastSubImgFunc contrastfunc) {
+ int i, j;
+ VSVector goodflds;
+ contrast_idx *ci =
+@@ -675,7 +688,7 @@ VSVector selectfields(MotionDetect* md, contrastSubImgFunc contrastfunc) {
+ for (i = 0; i < md->fieldNum; i++) {
+ ci[i].contrast = contrastfunc(md, &md->fields[i]);
+ ci[i].index = i;
+- if (ci[i].contrast < md->contrastThreshold)
++ if (ci[i].contrast < md->conf.contrastThreshold)
+ ci[i].contrast = 0;
+ // else printf("%i %lf\n", ci[i].index, ci[i].contrast);
+ }
+@@ -735,7 +748,7 @@ VSVector selectfields(MotionDetect* md, contrastSubImgFunc contrastfunc) {
+ * calculate rotation angle as cleaned mean of all angles
+ * compensate for possibly off-center rotation
+ */
+-LocalMotions calcTransFields(MotionDetect* md,
++LocalMotions calcTransFields(VSMotionDetect* md,
+ calcFieldTransFunc fieldfunc,
+ contrastSubImgFunc contrastfunc) {
+ LocalMotions localmotions;
+@@ -758,7 +771,7 @@ LocalMotions calcTransFields(MotionDetect* md,
+ for(index=0; index < vs_vector_size(&goodflds); index++){
+ int i = ((contrast_idx*)vs_vector_get(&goodflds,index))->index;
+ LocalMotion m;
+- m = fieldfunc(md, &md->fields[i], i); // e.g. calcFieldTransYUV
++ m = fieldfunc(md, &md->fields[i], i); // e.g. calcFieldTransPlanar
+ m.contrast = ((contrast_idx*)vs_vector_get(&goodflds,index))->contrast;
+ #ifdef STABVERBOSE
+ fprintf(file, "%i %i\n%f %f %f %f\n \n\n", m.f.x, m.f.y,
+@@ -772,13 +785,13 @@ LocalMotions calcTransFields(MotionDetect* md,
+ num_motions = vs_vector_size(&localmotions); // amount of transforms we actually have
+ vs_vector_del(&goodflds);
+ if (num_motions < 1) {
+- vs_log_warn(md->modName, "too low contrast! No field remains.\n \
++ vs_log_warn(md->conf.modName, "too low contrast! No field remains.\n \
+ (no translations are detected in frame %i)", md->frameNum);
+ }
+
+- if (md->show) { // draw fields and transforms into frame.
++ if (md->conf.show) { // draw fields and transforms into frame.
+ // this has to be done one after another to handle possible overlap
+- if (md->show > 1) {
++ if (md->conf.show > 1) {
+ for (i = 0; i < num_motions; i++)
+ drawFieldScanArea(md, LMGet(&localmotions,i));
+ }
+@@ -798,7 +811,7 @@ LocalMotions calcTransFields(MotionDetect* md,
+
+
+ /** draws the field scanning area */
+-void drawFieldScanArea(MotionDetect* md, const LocalMotion* lm) {
++void drawFieldScanArea(VSMotionDetect* md, const LocalMotion* lm) {
+ if (md->fi.pFormat > PF_PACKED)
+ return;
+ drawBox(md->currorig.data[0], md->currorig.linesize[0], md->fi.height, 1, lm->f.x, lm->f.y,
+@@ -806,7 +819,7 @@ void drawFieldScanArea(MotionDetect* md, const LocalMotion* lm) {
+ }
+
+ /** draws the field */
+-void drawField(MotionDetect* md, const LocalMotion* lm) {
++void drawField(VSMotionDetect* md, const LocalMotion* lm) {
+ if (md->fi.pFormat > PF_PACKED)
+ return;
+ drawBox(md->currorig.data[0], md->currorig.linesize[0], md->fi.height, 1, lm->f.x, lm->f.y,
+@@ -814,7 +827,7 @@ void drawField(MotionDetect* md, const LocalMotion* lm) {
+ }
+
+ /** draws the transform data of this field */
+-void drawFieldTrans(MotionDetect* md, const LocalMotion* lm) {
++void drawFieldTrans(VSMotionDetect* md, const LocalMotion* lm) {
+ if (md->fi.pFormat > PF_PACKED)
+ return;
+ drawBox(md->currorig.data[0], md->currorig.linesize[0], md->fi.height, 1,
+@@ -828,7 +841,7 @@ void drawFieldTrans(MotionDetect* md, const LocalMotion* lm) {
+ (the same for all channels)
+ */
+ void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, int x,
+- int y, int sizex, int sizey, unsigned char color) {
++ int y, int sizex, int sizey, unsigned char color) {
+
+ unsigned char* p = NULL;
+ int j, k;
+@@ -842,18 +855,18 @@ void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, int x,
+ }
+ }
+
+-// void addTrans(MotionDetect* md, Transform sl) {
++// void addTrans(VSMotionDetect* md, VSTransform sl) {
+ // if (!md->transs) {
+ // md->transs = vs_list_new(0);
+ // }
+ // vs_list_append_dup(md->transs, &sl, sizeof(sl));
+ // }
+
+-// Transform getLastTransform(MotionDetect* md){
++// VSTransform getLastVSTransform(VSMotionDetect* md){
+ // if (!md->transs || !md->transs->head) {
+ // return null_transform();
+ // }
+-// return *((Transform*)md->transs->tail);
++// return *((VSTransform*)md->transs->tail);
+ // }
+
+
+@@ -861,8 +874,8 @@ void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, int x,
+ /// plain C implementation of compareSubImg (without ORC)
+ unsigned int compareSubImg_thr(unsigned char* const I1, unsigned char* const I2,
+ const Field* field, int width1, int width2, int height,
+- int bytesPerPixel, int d_x, int d_y,
+- unsigned int threshold) {
++ int bytesPerPixel, int d_x, int d_y,
++ unsigned int threshold) {
+ int k, j;
+ unsigned char* p1 = NULL;
+ unsigned char* p2 = NULL;
+diff --git a/src/motiondetect.h b/src/motiondetect.h
+index ac225f8..1fabb34 100644
+--- a/src/motiondetect.h
++++ b/src/motiondetect.h
+@@ -36,58 +36,51 @@
+ #include "vsvector.h"
+ #include "frameinfo.h"
+
+-#define USE_SPIRAL_FIELD_CALC
++typedef struct _vsmotiondetectconfig {
++ /* meta parameter for maxshift and fieldsize between 1 and 15 */
++ int shakiness;
++ int accuracy; // meta parameter for number of fields between 1 and 10
++ int stepSize; // stepsize of field transformation detection
++ int algo; // algorithm to use
++ /* if >0 then all the frames are compared with the given frame (1 for first) */
++ int virtualTripod;
++ /* if 1 and 2 then the fields and transforms are shown in the frames */
++ int show;
++ /* measurement fields with lower contrast are discarded */
++ double contrastThreshold;
++ const char* modName; // module name (used for logging)
++} VSMotionDetectConfig;
+
+
+ /** data structure for motion detection part of deshaking*/
+-typedef struct motiondetect {
++typedef struct _vsmotiondetect {
+ VSFrameInfo fi;
+
+- VSFrame curr; // blurred version of current frame buffer
+- VSFrame currorig; // current frame buffer (original) (only pointer)
+- VSFrame currtmp; // temporary buffer for blurring
+- VSFrame prev; // frame buffer for last frame (copied)
+- short hasSeenOneFrame; // true if we have a valid previous frame
++ VSMotionDetectConfig conf;
+
+- const char* modName;
+-
+- Field* fields;
+-
+- /* Options */
+ /* maximum number of pixels we expect the shift of subsequent frames */
+ int maxShift;
+- int stepSize; // stepsize of field transformation detection
+- int allowMax; // 1 if maximal shift is allowed
+- int algo; // algorithm to use
+- int fieldNum; // number of measurement fields
+- int maxFields; // maximum number of fields used (selected by contrast)
+- int fieldSize; // size = min(md->width, md->height)/10;
+- int fieldRows; // number of rows
+- /* if >0 then all the frames are compared with the given frame (1 for first) */
+- int virtualTripod;
+- /* if 1 and 2 then the fields and transforms are shown in the frames */
+- int show;
+- /* measurement fields with lower contrast are discarded */
+- double contrastThreshold;
+- /* meta parameter for maxshift and fieldsize between 1 and 15 */
+- int shakiness;
+- int accuracy; // meta parameter for number of fields between 1 and 10
+-
+- int initialized; // 1 if initialized and 2 if configured
++ int allowMax; // 1 if maximal shift is allowed
++ int fieldNum; // number of measurement fields
++ int maxFields; // maximum number of fields used (selected by contrast)
++ int fieldSize; // size = min(md->width, md->height)/10;
++ int fieldRows; // number of rows
++
++ VSFrame curr; // blurred version of current frame buffer
++ VSFrame currorig; // current frame buffer (original) (only pointer)
++ VSFrame currtmp; // temporary buffer for blurring
++ VSFrame prev; // frame buffer for last frame (copied)
++ short hasSeenOneFrame; // true if we have a valid previous frame
+
+- int frameNum;
+-} MotionDetect;
++ Field* fields;
+
+-/* type for a function that calculates the transformation of a certain field
+- */
+-typedef LocalMotion (*calcFieldTransFunc)(MotionDetect*, const Field*, int);
++ int initialized; // 1 if initialized and 2 if configured
+
+-/* type for a function that calculates the contrast of a certain field
+- */
+-typedef double (*contrastSubImgFunc)(MotionDetect*, const Field*);
++ int frameNum;
++} VSMotionDetect;
+
+
+-static const char motiondetect_help[] = ""
++static const char vs_motiondetect_help[] = ""
+ "Overview:\n"
+ " Generates a file with relative transform information\n"
+ " (translation, rotation) about subsequent frames."
+@@ -96,9 +89,9 @@ static const char motiondetect_help[] = ""
+ " 'result' path to the file used to write the transforms\n"
+ " (def:inputfile.stab)\n"
+ " 'shakiness' how shaky is the video and how quick is the camera?\n"
+- " 1: little (fast) 10: very strong/quick (slow) (def: 4)\n"
++ " 1: little (fast) 10: very strong/quick (slow) (def: 5)\n"
+ " 'accuracy' accuracy of detection process (>=shakiness)\n"
+- " 1: low (fast) 15: high (slow) (def: 4)\n"
++ " 1: low (fast) 15: high (slow) (def: 9)\n"
+ " 'stepsize' stepsize of search process, region around minimum \n"
+ " is scanned with 1 pixel resolution (def: 6)\n"
+ " 'algo' 0: brute force (translation only);\n"
+@@ -111,16 +104,16 @@ static const char motiondetect_help[] = ""
+ " 'help' print this help message\n";
+
+
+-/** initialized the MotionDetect structure and allocates memory
+- * for the frames and stuff
+- * @return VS_OK on success otherwise VS_ERROR
++/** returns the default config
+ */
+-int initMotionDetect(MotionDetect* md, const VSFrameInfo* fi, const char* modName);
++VSMotionDetectConfig vsMotionDetectGetDefaulfConfig(const char* modName);
+
+-/** configures MotionDetect structure and checks ranges, initializes fields and so on.
++/** initialized the VSMotionDetect structure and allocates memory
++ * for the frames and stuff
+ * @return VS_OK on success otherwise VS_ERROR
+ */
+-int configureMotionDetect(MotionDetect* md);
++int vsMotionDetectInit(VSMotionDetect* md, const VSMotionDetectConfig* conf,
++ const VSFrameInfo* fi);
+
+ /**
+ * Performs a motion detection step
+@@ -128,49 +121,18 @@ int configureMotionDetect(MotionDetect* md);
+ * is stored internally
+ * @param motions: calculated local motions. (must be deleted manually)
+ * */
+-int motionDetection(MotionDetect* md, LocalMotions* motions, VSFrame *frame);
++int vsMotionDetection(VSMotionDetect* md, LocalMotions* motions, VSFrame *frame);
+
+ /** Deletes internal data structures.
+- * In order to use the MotionDetect again, you have to call initMotionDetect
++ * In order to use the VSMotionDetect again, you have to call vsMotionDetectInit
+ */
+-void cleanupMotionDetection(MotionDetect* md);
+-
+-
+-int initFields(MotionDetect* md);
+-unsigned int compareImg(unsigned char* I1, unsigned char* I2, int width, int height,
+- int bytesPerPixel, int strive1, int strive2, int d_x, int d_y);
+-
+-double contrastSubImgYUV(MotionDetect* md, const Field* field);
+-double contrastSubImgRGB(MotionDetect* md, const Field* field);
+-double contrastSubImg(unsigned char* const I, const Field* field,
+- int width, int height, int bytesPerPixel);
+-
+-
+-int cmp_contrast_idx(const void *ci1, const void* ci2);
+-VSVector selectfields(MotionDetect* md, contrastSubImgFunc contrastfunc);
+-
+-LocalMotions calcShiftRGBSimple(MotionDetect* md);
+-LocalMotions calcShiftYUVSimple(MotionDetect* md);
+-
+-LocalMotion calcFieldTransYUV(MotionDetect* md, const Field* field,
+- int fieldnum);
+-LocalMotion calcFieldTransRGB(MotionDetect* md, const Field* field,
+- int fieldnum);
+-LocalMotions calcTransFields(MotionDetect* md, calcFieldTransFunc fieldfunc,
+- contrastSubImgFunc contrastfunc);
+-
+-
+-void drawFieldScanArea(MotionDetect* md, const LocalMotion* motion);
+-void drawField(MotionDetect* md, const LocalMotion* motion);
+-void drawFieldTrans(MotionDetect* md, const LocalMotion* motion);
+-void drawBox(unsigned char* I, int width, int height, int bytesPerPixel,
+- int x, int y, int sizex, int sizey, unsigned char color);
++void vsMotionDetectionCleanup(VSMotionDetect* md);
+
++/// returns the current config
++void vsMotionDetectGetConfig(VSMotionDetectConfig* conf, const VSMotionDetect* md);
+
+-unsigned int compareSubImg_thr(unsigned char* const I1, unsigned char* const I2,
+- const Field* field, int width1, int width2, int height,
+- int bytesPerPixel,
+- int d_x, int d_y, unsigned int threshold);
++/// returns the frame info
++const VSFrameInfo* vsMotionDetectGetFrameInfo(const VSMotionDetect* md);
+
+ #endif /* MOTIONDETECT_H */
+
+@@ -179,7 +141,8 @@ unsigned int compareSubImg_thr(unsigned char* const I1, unsigned char* const I2,
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
++ * c-basic-offset: 2 t
+ * End:
+ *
+- * vim: expandtab shiftwidth=4:
++ * vim: expandtab shiftwidth=2:
+ */
+diff --git a/src/motiondetect_internal.h b/src/motiondetect_internal.h
+new file mode 100644
+index 0000000..3b71ef4
+--- /dev/null
++++ b/src/motiondetect_internal.h
+@@ -0,0 +1,89 @@
++/*
++ * motiondetect_internal.h
++ *
++ * Copyright (C) Georg Martius - February 2011
++ * georg dot martius at web dot de
++ * Copyright (C) Alexey Osipov - Jule 2011
++ * simba at lerlan dot ru
++ * speed optimizations (threshold, spiral, SSE, asm)
++ *
++ * This file is part of vid.stab video stabilization library
++ *
++ * vid.stab 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, or
++ * (at your option) any later version.
++ *
++ * vid.stab 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 GNU Make; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#ifndef MOTIONDETECT_INTERNAL_H
++#define MOTIONDETECT_INTERNAL_H
++
++#include "motiondetect.h"
++
++/* type for a function that calculates the transformation of a certain field
++ */
++typedef LocalMotion (*calcFieldTransFunc)(VSMotionDetect*, const Field*, int);
++
++/* type for a function that calculates the contrast of a certain field
++ */
++typedef double (*contrastSubImgFunc)(VSMotionDetect*, const Field*);
++
++
++int initFields(VSMotionDetect* md);
++unsigned int compareImg(unsigned char* I1, unsigned char* I2, int width, int height,
++ int bytesPerPixel, int strive1, int strive2, int d_x, int d_y);
++
++double contrastSubImgPlanar(VSMotionDetect* md, const Field* field);
++double contrastSubImgPacked(VSMotionDetect* md, const Field* field);
++double contrastSubImg(unsigned char* const I, const Field* field,
++ int width, int height, int bytesPerPixel);
++
++
++int cmp_contrast_idx(const void *ci1, const void* ci2);
++VSVector selectfields(VSMotionDetect* md, contrastSubImgFunc contrastfunc);
++
++LocalMotions calcShiftPackedSimple(VSMotionDetect* md);
++LocalMotions calcShiftPlanarSimple(VSMotionDetect* md);
++
++LocalMotion calcFieldTransPlanar(VSMotionDetect* md, const Field* field,
++ int fieldnum);
++LocalMotion calcFieldTransPacked(VSMotionDetect* md, const Field* field,
++ int fieldnum);
++LocalMotions calcTransFields(VSMotionDetect* md, calcFieldTransFunc fieldfunc,
++ contrastSubImgFunc contrastfunc);
++
++
++void drawFieldScanArea(VSMotionDetect* md, const LocalMotion* motion);
++void drawField(VSMotionDetect* md, const LocalMotion* motion);
++void drawFieldTrans(VSMotionDetect* md, const LocalMotion* motion);
++void drawBox(unsigned char* I, int width, int height, int bytesPerPixel,
++ int x, int y, int sizex, int sizey, unsigned char color);
++
++
++unsigned int compareSubImg_thr(unsigned char* const I1, unsigned char* const I2,
++ const Field* field, int width1, int width2, int height,
++ int bytesPerPixel,
++ int d_x, int d_y, unsigned int threshold);
++
++#endif /* MOTIONDETECT_INTERNAL_H */
++
++/*
++ * Local variables:
++ * c-file-style: "stroustrup"
++ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
++ * indent-tabs-mode: nil
++ * c-basic-offset: 2 t
++ * End:
++ *
++ * vim: expandtab shiftwidth=2:
++ */
+diff --git a/src/motiondetect_opt.c b/src/motiondetect_opt.c
+index 5510c84..de63e3b 100644
+--- a/src/motiondetect_opt.c
++++ b/src/motiondetect_opt.c
+@@ -39,7 +39,7 @@
+
+ #ifdef USE_SSE2
+ /**
+- \see contrastSubImg using SSE2 optimization, YUV (1 byte per channel) only
++ \see contrastSubImg using SSE2 optimization, Planar (1 byte per channel) only
+ */
+ double contrastSubImg1_SSE(unsigned char* const I, const Field* field,
+ int width, int height)
+@@ -171,9 +171,9 @@ double contrastSubImg_variance_C(unsigned char* const I,
+ \param d_y shift in y direction
+ */
+ unsigned int compareSubImg_thr_orc(unsigned char* const I1, unsigned char* const I2,
+- const Field* field, int width1, int width2, int height,
+- int bytesPerPixel, int d_x, int d_y,
+- unsigned int threshold) {
++ const Field* field, int width1, int width2, int height,
++ int bytesPerPixel, int d_x, int d_y,
++ unsigned int threshold) {
+ unsigned char* p1 = NULL;
+ unsigned char* p2 = NULL;
+ int s2 = field->size / 2;
+@@ -198,9 +198,9 @@ unsigned int compareSubImg_thr_orc(unsigned char* const I1, unsigned char* const
+
+ // implementation with 1 orc function, but no threshold
+ unsigned int compareSubImg_orc(unsigned char* const I1, unsigned char* const I2,
+- const Field* field, int width1, int width2, int height,
+- int bytesPerPixel, int d_x, int d_y,
+- unsigned int threshold) {
++ const Field* field, int width1, int width2, int height,
++ int bytesPerPixel, int d_x, int d_y,
++ unsigned int threshold) {
+ unsigned char* p1 = NULL;
+ unsigned char* p2 = NULL;
+ int s2 = field->size / 2;
+@@ -217,12 +217,12 @@ unsigned int compareSubImg_orc(unsigned char* const I1, unsigned char* const I2,
+
+ #ifdef USE_SSE2
+ unsigned int compareSubImg_thr_sse2(unsigned char* const I1, unsigned char* const I2,
+- const Field* field,
+- int width1, int width2, int height,
+- int bytesPerPixel, int d_x, int d_y,
+- unsigned int treshold) {
+- int k, j;
+- unsigned char* p1 = NULL;
++ const Field* field,
++ int width1, int width2, int height,
++ int bytesPerPixel, int d_x, int d_y,
++ unsigned int treshold) {
++ int k, j;
++ unsigned char* p1 = NULL;
+ unsigned char* p2 = NULL;
+ int s2 = field->size / 2;
+ unsigned int sum = 0;
+diff --git a/src/serialize.c b/src/serialize.c
+index 603774e..cf167bc 100644
+--- a/src/serialize.c
++++ b/src/serialize.c
+@@ -23,9 +23,11 @@
+ */
+
+ #include <assert.h>
++#include <string.h>
+
+ #include "serialize.h"
+ #include "transformtype.h"
++#include "transformtype_operations.h"
+ #include "motiondetect.h"
+
+ const char* modname = "vid.stab - serialization";
+@@ -53,7 +55,7 @@ LocalMotion restoreLocalmotion(FILE* f){
+ return lm;
+ }
+
+-int storeLocalmotions(FILE* f, const LocalMotions* lms){
++int vsStoreLocalmotions(FILE* f, const LocalMotions* lms){
+ int len = vs_vector_size(lms);
+ int i;
+ fprintf(f,"List %i [",len);
+@@ -66,7 +68,7 @@ int storeLocalmotions(FILE* f, const LocalMotions* lms){
+ }
+
+ /// restores local motions from file
+-LocalMotions restoreLocalmotions(FILE* f){
++LocalMotions vsRestoreLocalmotions(FILE* f){
+ LocalMotions lms;
+ int i;
+ char c;
+@@ -96,99 +98,98 @@ LocalMotions restoreLocalmotions(FILE* f){
+ return lms;
+ }
+
+-int prepareFile(const MotionDetect* md, FILE* f){
++int vsPrepareFile(const VSMotionDetect* md, FILE* f){
+ if(!f) return VS_ERROR;
+ fprintf(f, "VID.STAB 1\n");
+- // fprintf(f, "# accuracy = %d\n", md->accuracy);
+- fprintf(f, "# accuracy = %d\n", md->accuracy);
+- fprintf(f, "# shakiness = %d\n", md->shakiness);
+- fprintf(f, "# stepsize = %d\n", md->stepSize);
+- fprintf(f, "# algo = %d\n", md->algo);
+- fprintf(f, "# mincontrast = %f\n", md->contrastThreshold);
++ fprintf(f, "# accuracy = %d\n", md->conf.accuracy);
++ fprintf(f, "# shakiness = %d\n", md->conf.shakiness);
++ fprintf(f, "# stepsize = %d\n", md->conf.stepSize);
++ fprintf(f, "# algo = %d\n", md->conf.algo);
++ fprintf(f, "# mincontrast = %f\n", md->conf.contrastThreshold);
+ return VS_OK;
+ }
+
+-int writeToFile(const MotionDetect* md, FILE* f, const LocalMotions* lms){
+- if(!f || !lms) return VS_ERROR;
++int vsWriteToFile(const VSMotionDetect* md, FILE* f, const LocalMotions* lms){
++ if(!f || !lms) return VS_ERROR;
+
+- if(fprintf(f, "Frame %i (", md->frameNum)>0
+- && storeLocalmotions(f,lms)>0 && fprintf(f, ")\n"))
+- return VS_OK;
+- else
+- return VS_ERROR;
++ if(fprintf(f, "Frame %i (", md->frameNum)>0
++ && vsStoreLocalmotions(f,lms)>0 && fprintf(f, ")\n"))
++ return VS_OK;
++ else
++ return VS_ERROR;
+ }
+
+ /// reads the header of the file and return the version number
+-int readFileVersion(FILE* f){
+- if(!f) return VS_ERROR;
+- int version;
+- if(fscanf(f, "VID.STAB %i\n", &version)!=1)
+- return VS_ERROR;
+- else return version;
++int vsReadFileVersion(FILE* f){
++ if(!f) return VS_ERROR;
++ int version;
++ if(fscanf(f, "VID.STAB %i\n", &version)!=1)
++ return VS_ERROR;
++ else return version;
+ }
+
+-int readFromFile(FILE* f, LocalMotions* lms){
+- char c = fgetc(f);
+- if(c=='F') {
+- int num;
+- if(fscanf(f,"rame %i (", &num)!=1) {
+- vs_log_error(modname,"cannot read file, expect 'Frame num (...'");
+- return VS_ERROR;
+- }
+- *lms = restoreLocalmotions(f);
+- if(fscanf(f,")\n")<0) {
+- vs_log_error(modname,"cannot read file, expect '...)'");
+- return VS_ERROR;
+- }
+- return num;
+- } else if(c=='#') {
+- char l[1024];
++int vsReadFromFile(FILE* f, LocalMotions* lms){
++ char c = fgetc(f);
++ if(c=='F') {
++ int num;
++ if(fscanf(f,"rame %i (", &num)!=1) {
++ vs_log_error(modname,"cannot read file, expect 'Frame num (...'");
++ return VS_ERROR;
++ }
++ *lms = vsRestoreLocalmotions(f);
++ if(fscanf(f,")\n")<0) {
++ vs_log_error(modname,"cannot read file, expect '...)'");
++ return VS_ERROR;
++ }
++ return num;
++ } else if(c=='#') {
++ char l[1024];
+ if(fgets(l, sizeof(l), f)==0) return VS_ERROR;
+- return readFromFile(f,lms);
+- } else if(c=='\n' || c==' ') {
+- return readFromFile(f,lms);
+- } else if(c==EOF) {
+- return VS_ERROR;
+- } else {
+- vs_log_error(modname,"cannot read frame local motions from file, got %c (%i)",
+- c, (int) c);
+- return VS_ERROR;
+- }
++ return vsReadFromFile(f,lms);
++ } else if(c=='\n' || c==' ') {
++ return vsReadFromFile(f,lms);
++ } else if(c==EOF) {
++ return VS_ERROR;
++ } else {
++ vs_log_error(modname,"cannot read frame local motions from file, got %c (%i)",
++ c, (int) c);
++ return VS_ERROR;
++ }
+ }
+
+-int readLocalMotionsFile(FILE* f, ManyLocalMotions* mlms){
+- int version = readFileVersion(f);
+- if(version<1) // old format or unknown
+- return VS_ERROR;
+- if(version>1){
+- vs_log_error(modname,"Version of VID.STAB file too large: got %i, expect <= 1",
+- version);
+- return VS_ERROR;
+- }
+- assert(mlms);
+- // initial number of frames, but it will automatically be increaseed
+- vs_vector_init(mlms,1024);
+- int index;
+- int oldindex = 0;
+- LocalMotions lms;
+- while((index = readFromFile(f,&lms)) != VS_ERROR){
+- if(index > oldindex+1){
+- vs_log_info(modname,"VID.STAB file: index of frames is not continuous %i -< %i",
+- oldindex, index);
+- }
+- if(index<1){
+- vs_log_info(modname,"VID.STAB file: Frame number < 1 (%i)", index);
+- } else {
+- vs_vector_set_dup(mlms,index-1,&lms, sizeof(LocalMotions));
+- }
+- oldindex=index;
+- }
+- return VS_OK;
++int vsReadLocalMotionsFile(FILE* f, VSManyLocalMotions* mlms){
++ int version = vsReadFileVersion(f);
++ if(version<1) // old format or unknown
++ return VS_ERROR;
++ if(version>1){
++ vs_log_error(modname,"Version of VID.STAB file too large: got %i, expect <= 1",
++ version);
++ return VS_ERROR;
++ }
++ assert(mlms);
++ // initial number of frames, but it will automatically be increaseed
++ vs_vector_init(mlms,1024);
++ int index;
++ int oldindex = 0;
++ LocalMotions lms;
++ while((index = vsReadFromFile(f,&lms)) != VS_ERROR){
++ if(index > oldindex+1){
++ vs_log_info(modname,"VID.STAB file: index of frames is not continuous %i -< %i",
++ oldindex, index);
++ }
++ if(index<1){
++ vs_log_info(modname,"VID.STAB file: Frame number < 1 (%i)", index);
++ } else {
++ vs_vector_set_dup(mlms,index-1,&lms, sizeof(LocalMotions));
++ }
++ oldindex=index;
++ }
++ return VS_OK;
+ }
+
+
+ /**
+- * readOldTransforms: read transforms file (Deprecated format)
++ * vsReadOldTransforms: read transforms file (Deprecated format)
+ * The format is as follows:
+ * Lines with # at the beginning are comments and will be ignored
+ * Data lines have 5 columns seperated by space or tab containing
+@@ -203,53 +204,54 @@ int readLocalMotionsFile(FILE* f, ManyLocalMotions* mlms){
+ * number of transforms read
+ * Preconditions: f is opened
+ */
+-int readOldTransforms(const TransformData* td, FILE* f , Transformations* trans)
++int vsReadOldTransforms(const VSTransformData* td, FILE* f , VSTransformations* trans)
+ {
+- char l[1024];
+- int s = 0;
+- int i = 0;
+- int ti; // time (ignored)
+- Transform t;
++ char l[1024];
++ int s = 0;
++ int i = 0;
++ int ti; // time (ignored)
++ VSTransform t;
+
+- while (fgets(l, sizeof(l), f)) {
+- if (l[0] == '#')
+- continue; // ignore comments
+- if (strlen(l) == 0)
+- continue; // ignore empty lines
+- // try new format
+- if (sscanf(l, "%i %lf %lf %lf %lf %i", &ti, &t.x, &t.y, &t.alpha,
+- &t.zoom, &t.extra) != 6) {
+- if (sscanf(l, "%i %lf %lf %lf %i", &ti, &t.x, &t.y, &t.alpha,
+- &t.extra) != 5) {
+- vs_log_error(td->modName, "Cannot parse line: %s", l);
+- return 0;
+- }
+- t.zoom=0;
+- }
++ while (fgets(l, sizeof(l), f)) {
++ t = null_transform();
++ if (l[0] == '#')
++ continue; // ignore comments
++ if (strlen(l) == 0)
++ continue; // ignore empty lines
++ // try new format
++ if (sscanf(l, "%i %lf %lf %lf %lf %i", &ti, &t.x, &t.y, &t.alpha,
++ &t.zoom, &t.extra) != 6) {
++ if (sscanf(l, "%i %lf %lf %lf %i", &ti, &t.x, &t.y, &t.alpha,
++ &t.extra) != 5) {
++ vs_log_error(td->conf.modName, "Cannot parse line: %s", l);
++ return 0;
++ }
++ t.zoom=0;
++ }
+
+- if (i>=s) { // resize transform array
+- if (s == 0)
+- s = 256;
+- else
+- s*=2;
+- /* vs_log_info(td->modName, "resize: %i\n", s); */
+- trans->ts = vs_realloc(trans->ts, sizeof(Transform)* s);
+- if (!trans->ts) {
+- vs_log_error(td->modName, "Cannot allocate memory"
+- " for transformations: %i\n", s);
+- return 0;
+- }
+- }
+- trans->ts[i] = t;
+- i++;
++ if (i>=s) { // resize transform array
++ if (s == 0)
++ s = 256;
++ else
++ s*=2;
++ /* vs_log_info(td->modName, "resize: %i\n", s); */
++ trans->ts = vs_realloc(trans->ts, sizeof(VSTransform)* s);
++ if (!trans->ts) {
++ vs_log_error(td->conf.modName, "Cannot allocate memory"
++ " for transformations: %i\n", s);
++ return 0;
++ }
+ }
+- trans->len = i;
++ trans->ts[i] = t;
++ i++;
++ }
++ trans->len = i;
+
+- return i;
++ return i;
+ }
+
+
+-// t = simpleMotionsToTransform(md, &localmotions);
++// t = vsSimpleMotionsToTransform(md, &localmotions);
+
+
+ /*
+diff --git a/src/serialize.h b/src/serialize.h
+index 9018306..2142a7d 100644
+--- a/src/serialize.h
++++ b/src/serialize.h
+@@ -31,33 +31,33 @@
+
+
+ /// Vector of LocalMotions
+-typedef VSVector ManyLocalMotions;
++typedef VSVector VSManyLocalMotions;
+ /// helper macro to access a localmotions vector in the VSVector of all Frames
+-#define MLMGet(manylocalmotions,index) \
++#define VSMLMGet(manylocalmotions,index) \
+ ((LocalMotions*)vs_vector_get(manylocalmotions,index))
+
+
+ /// stores local motions to file
+-int storeLocalmotions(FILE* f, const LocalMotions* lms);
++int vsStoreLocalmotions(FILE* f, const LocalMotions* lms);
+
+ /// restores local motions from file
+-LocalMotions restoreLocalmotions(FILE* f);
++LocalMotions vsRestoreLocalmotions(FILE* f);
+
+
+ /// writes the header to the file that is to be holding the local motions
+-int prepareFile(const MotionDetect* td, FILE* f);
++int vsPrepareFile(const VSMotionDetect* td, FILE* f);
+
+ /// appends the given localmotions to the file
+-int writeToFile(const MotionDetect* td, FILE* f, const LocalMotions* lms);
++int vsWriteToFile(const VSMotionDetect* td, FILE* f, const LocalMotions* lms);
+
+ /// reads the header of the file and return the version number (used by readLocalmotionsFile)
+-int readFileVersion(FILE* f);
++int vsReadFileVersion(FILE* f);
+
+ /*
+ * reads the next set of localmotions from the file, return VS_ERROR on error or
+ * if nothing is read (used by readLocalmotionsFile)
+ */
+-int readFromFile(FILE* f, LocalMotions* lms);
++int vsReadFromFile(FILE* f, LocalMotions* lms);
+
+ /*
+ * reads the entire file of localmotions, return VS_ERROR on error or if nothing is read
+@@ -68,10 +68,10 @@ int readFromFile(FILE* f, LocalMotions* lms);
+ * Data lines have the structure: Frame NUM (<LocalMotions>)
+ * where LocalMotions ::= List [(LM v.x v.y f.x f.y f.size contrast match),...]
+ */
+-int readLocalMotionsFile(FILE* f, ManyLocalMotions* lms);
++int vsReadLocalMotionsFile(FILE* f, VSManyLocalMotions* lms);
+
+ // read the transformations from the given file (Deprecated format)
+-int readOldTransforms(const TransformData* td, FILE* f , Transformations* trans);
++int vsReadOldTransforms(const VSTransformData* td, FILE* f , VSTransformations* trans);
+
+
+ #endif
+diff --git a/src/transform.c b/src/transform.c
+index 7e7a9e0..bb02f53 100644
+--- a/src/transform.c
++++ b/src/transform.c
+@@ -23,6 +23,8 @@
+ */
+
+ #include "transform.h"
++#include "transform_internal.h"
++#include "transformtype_operations.h"
+
+ #include "transformfixedpoint.h"
+ #ifdef TESTING
+@@ -31,159 +33,185 @@
+
+ #include <math.h>
+ #include <libgen.h>
++#include <string.h>
+
+-const char* interpolTypes[5] = {"No (0)", "Linear (1)", "Bi-Linear (2)",
+- "Bi-Cubic (3)"};
++const char* interpol_type_names[5] = {"No (0)", "Linear (1)", "Bi-Linear (2)",
++ "Bi-Cubic (3)"};
+
++const char* getInterpolationTypeName(VSInterpolType type){
++ if (type >= VS_Zero && type < VS_NBInterPolTypes)
++ return interpol_type_names[(int) type];
++ else
++ return "unknown";
++}
+
+-int initTransformData(TransformData* td, const VSFrameInfo* fi_src,
+- const VSFrameInfo* fi_dest , const char* modName){
+- td->modName = modName;
++VSTransformConfig vsTransformGetDefaulfConfig(const char* modName){
++ VSTransformConfig conf;
++ /* Options */
++ conf.maxShift = -1;
++ conf.maxAngle = -1;
++ conf.crop = VSKeepBorder;
++ conf.relative = 1;
++ conf.invert = 0;
++ conf.smoothing = 10;
++ conf.zoom = 0;
++ conf.optZoom = 1;
++ conf.interpolType = VS_BiLinear;
++ conf.verbose = 0;
++ conf.modName = modName;
++ return conf;
++}
+
+- td->fiSrc = *fi_src;
+- td->fiDest = *fi_dest;
++void vsTransformGetConfig(VSTransformConfig* conf, const VSTransformData* td){
++ if(td && conf)
++ *conf = td->conf;
++}
+
+- nullFrame(&td->src);
+- td->srcMalloced = 0;
++const VSFrameInfo* vsTransformGetSrcFrameInfo(const VSTransformData* td){
++ return &td->fiSrc;
++}
+
+- nullFrame(&td->destbuf);
+- nullFrame(&td->dest);
++const VSFrameInfo* vsTransformGetDestFrameInfo(const VSTransformData* td){
++ return &td->fiDest;
++}
+
+- /* Options */
+- td->maxShift = -1;
+- td->maxAngle = -1;
+- td->maxAngleVariation = 1;
+
++int vsTransformDataInit(VSTransformData* td, const VSTransformConfig* conf,
++ const VSFrameInfo* fi_src, const VSFrameInfo* fi_dest){
++ td->conf = *conf;
+
+- td->crop = KeepBorder;
+- td->relative = 1;
+- td->invert = 0;
+- td->smoothing = 10;
++ td->fiSrc = *fi_src;
++ td->fiDest = *fi_dest;
+
+- td->rotationThreshhold = 0.25/(180/M_PI);
++ vsFrameNull(&td->src);
++ td->srcMalloced = 0;
+
+- td->zoom = 0;
+- td->optZoom = 1;
+- td->interpolType = BiLinear;
+- td->sharpen = 0.8;
++ vsFrameNull(&td->destbuf);
++ vsFrameNull(&td->dest);
<Skipped 4775 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/vid.stab.git/commitdiff/ca14007dbc5cc183b5dbeaa0abe448178f6b3234
More information about the pld-cvs-commit
mailing list