]> git.sesse.net Git - mlt/commitdiff
use calloc insteadt of malloc/memset
authorgmarco <g.marco@freenet.de>
Fri, 16 Dec 2011 11:16:06 +0000 (12:16 +0100)
committerDan Dennedy <dan@dennedy.org>
Mon, 26 Dec 2011 22:33:33 +0000 (14:33 -0800)
use struct for instance data
small cleanup
use PIX(n)
dont use instable yuv420
use stabilize on grayimage (converted from yuv422)

src/modules/videostab/filter_videostab2.c
src/modules/videostab/stabilize.c
src/modules/videostab/stabilize.h
src/modules/videostab/transform_image.c
src/modules/videostab/transform_image.h

index 875a3ac1ed0ccb06ad4e7fd5c2d79e7feb8922bb..b57d001d689717ff481ddfb43141b4c8a3451a74 100644 (file)
 #include "stabilize.h"
 #include "transform_image.h"
 
+typedef struct {
+       StabData* stab;
+       TransformData* trans;
+       int initialized;
+       void* parent;
+} videostab2_data;
 
-static void serialize_vectors( StabData* self, mlt_position length )
+static void serialize_vectors( videostab2_data* self, mlt_position length )
 {
        mlt_geometry g = mlt_geometry_init();
-
        if ( g )
        {
                struct mlt_geometry_item_s item;
@@ -46,7 +51,7 @@ static void serialize_vectors( StabData* self, mlt_position length )
                item.key = item.f[0] = item.f[1] = 1;
                item.f[2] = item.f[3] = item.f[4] = 1;
 
-               tlist* transform_data =self->transs;
+               tlist* transform_data =self->stab->transs;
                for ( i = 0; i < length; i++ )
                {
                        // Set the geometry item
@@ -81,8 +86,7 @@ Transform* deserialize_vectors( char *vectors, mlt_position length )
        {
                struct mlt_geometry_item_s item;
                int i;
-               tx=malloc(sizeof(Transform)*length);
-               memset(tx,sizeof(Transform)*length,0);
+               tx=calloc(1,sizeof(Transform)*length);
                // Copy the geometry items to a vc array for interp()
                for ( i = 0; i < length; i++ )
                {
@@ -95,7 +99,7 @@ Transform* deserialize_vectors( char *vectors, mlt_position length )
                        t.extra=0;
                        tx[i]=t;
                }
-               
+
        }
        else
        {
@@ -110,98 +114,99 @@ Transform* deserialize_vectors( char *vectors, mlt_position length )
 static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
        mlt_filter filter = mlt_frame_pop_service( frame );
-       if (*format != mlt_image_yuv420p){
-               return 1;
-       }
+       char *vectors = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "vectors" );
+       *format = mlt_image_yuv422;
+       if (vectors)
+               *format= mlt_image_rgb24;
        mlt_properties_set_int( MLT_FRAME_PROPERTIES(frame), "consumer_deinterlace", 1 );
        int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
 
        if ( !error && *image )
        {
-               StabData* self = filter->child;
+               videostab2_data* data = filter->child;
+               if ( data==NULL ) { // big error, abort
+                       return 1;
+               }
                mlt_position length = mlt_filter_get_length2( filter, frame );
                int h = *height;
                int w = *width;
 
                // Service locks are for concurrency control
                mlt_service_lock( MLT_FILTER_SERVICE( filter ) );
-               if ( !self->initialized )
-               {
-                       // Initialize our context
-                       self->initialized = 1;
-                       self->width=w;
-                       self->height=h;
-                       self->framesize=w*h* 3/2;//( mlt_image_format_size ( *format, w,h , 0) ; // 3/2 =1 too small
-                       self->shakiness = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "shakiness" );
-                       self->accuracy = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "accuracy" );
-                       self->stepsize = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "stepsize" );
-                       self->algo = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "algo" );
-                       self->show = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "show" );
-                       self->contrast_threshold = mlt_properties_get_double( MLT_FILTER_PROPERTIES(filter) , "mincontrast" );
-                       stabilize_configure(self);
-               }
-               char *vectors = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "vectors" );
-               if ( !vectors )
-               {
-                       // Analyse
-                       mlt_position pos = mlt_filter_get_position( filter, frame );
-                       stabilize_filter_video ( self, *image, *format );
 
-
-                       // On last frame
-                       if ( pos == length - 1 )
+               if ( !vectors) {
+                       if ( !data->initialized )
                        {
-                               serialize_vectors( self, length );
+                               // Initialize our context
+                               data->initialized = 1;
+                               data->stab->width=w;
+                               data->stab->height=h;
+                               if (*format==mlt_image_yuv420p) data->stab->framesize=w*h* 3/2;//( mlt_image_format_size ( *format, w,h , 0) ; // 3/2 =1 too small
+                               if (*format==mlt_image_yuv422) data->stab->framesize=w*h;
+                               data->stab->shakiness = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "shakiness" );
+                               data->stab->accuracy = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "accuracy" );
+                               data->stab->stepsize = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "stepsize" );
+                               data->stab->algo = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "algo" );
+                               data->stab->show = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter) , "show" );
+                               data->stab->contrast_threshold = mlt_properties_get_double( MLT_FILTER_PROPERTIES(filter) , "mincontrast" );
+                               stabilize_configure(data->stab);
                        }
+                               // Analyse
+                               mlt_position pos = mlt_filter_get_position( filter, frame );
+                               stabilize_filter_video ( data->stab , *image, *format );
+
+                               // On last frame
+                               if ( pos == length - 1 )
+                               {
+                                       serialize_vectors( data , length );
+                               }
                }
-               if ( vectors )
+               else
                {
-                       // Apply
-                       TransformData* tf=mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "_transformdata", NULL);
-                       char *interps = mlt_properties_get( MLT_FRAME_PROPERTIES( frame ), "rescale.interp" );
-
-                       if (!tf){
-                               tf=mlt_pool_alloc(sizeof(TransformData));
-                               mlt_properties_set_data( MLT_FILTER_PROPERTIES(filter), "_transformdata", tf, 0, ( mlt_destructor )mlt_pool_release, NULL );
-                       }
-                       if ( self->initialized != 2 )
+                       if ( data->initialized!=1  )
                        {
-                               // Load analysis results from property
-                               self->initialized = 2;
+                               char *interps = mlt_properties_get( MLT_FRAME_PROPERTIES( frame ), "rescale.interp" );
 
-                               int interp = 2;
-                               if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
-                                       interp = 0;
-                               else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
-                                       interp = 1;
-                               else if ( strcmp( interps, "bilinear" ) == 0 )
-                                       interp = 2;
-                               else if ( strcmp( interps, "bicubic" ) == 0 )
-                                       interp = 3;
-                               else if ( strcmp( interps, "bicublin" ) == 0 )
-                                       interp = 4;
+                               if ( data->initialized != 2 )
+                               {
+                                       // Load analysis results from property
+                                       data->initialized = 2;
 
-                               tf->interpoltype = interp;
-                               tf->smoothing = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "smoothing" ); 
-                               tf->maxshift = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "maxshift" ); 
-                               tf->maxangle = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "maxangle" ); 
-                               tf->crop = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "crop" ); 
-                               tf->invert = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "invert" ); 
-                               tf->relative = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "relative" ); 
-                               tf->zoom = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "zoom" ); 
-                               tf->optzoom = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "optzoom" ); 
-                               tf->sharpen = mlt_properties_get_double( MLT_FILTER_PROPERTIES(filter), "sharpen" ); 
+                                       int interp = 2;
+                                       if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
+                                               interp = 0;
+                                       else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
+                                               interp = 1;
+                                       else if ( strcmp( interps, "bilinear" ) == 0 )
+                                               interp = 2;
+                                       else if ( strcmp( interps, "bicubic" ) == 0 )
+                                               interp = 3;
+                                       else if ( strcmp( interps, "bicublin" ) == 0 )
+                                               interp = 4;
 
-                               transform_configure(tf,w,h,*format ,*image, deserialize_vectors(  vectors, length ),length);
-                               
-                       }
-                       if ( self->initialized == 2 )
-                       {
-                               // Stabilize
-                               float pos = mlt_filter_get_position( filter, frame );
-                               tf->current_trans=pos;
-                               transform_filter_video(tf, *image, *format );
-                       }
+                                       data->trans->interpoltype = interp;
+                                       data->trans->smoothing = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "smoothing" );
+                                       data->trans->maxshift = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "maxshift" );
+                                       data->trans->maxangle = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "maxangle" );
+                                       data->trans->crop = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "crop" );
+                                       data->trans->invert = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "invert" );
+                                       data->trans->relative = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "relative" );
+                                       data->trans->zoom = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "zoom" );
+                                       data->trans->optzoom = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "optzoom" );
+                                       data->trans->sharpen = mlt_properties_get_double( MLT_FILTER_PROPERTIES(filter), "sharpen" );
+
+                                       transform_configure(data->trans,w,h,*format ,*image, deserialize_vectors(  vectors, length ),length);
+
+                               }
+                               if ( data->initialized == 2 )
+                               {
+                                       // Stabilize
+                                       float pos = mlt_filter_get_position( filter, frame );
+                                       data->trans->current_trans=pos;
+                                       transform_filter_video(data->trans, *image, *format );
+
+                               }
+               }
                }
                mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
        }
@@ -217,41 +222,50 @@ static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
 
 static void filter_close( mlt_filter parent )
 {
-       StabData* self = parent->child;
-       stabilize_stop(self);
-       free( self );
+       videostab2_data* data = parent->child;
+       if (data){
+               if (data->stab) stabilize_stop(data->stab);
+               if (data->trans){
+                       if (data->trans->src) free(data->trans->src);
+                       free (data->trans);
+               }
+               free( data );
+       }
        parent->close = NULL;
        parent->child = NULL;
 }
 
 mlt_filter filter_videostab2_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
-       StabData* self = calloc( 1, sizeof(StabData) );
-       if ( self )
+       videostab2_data* data= calloc( 1, sizeof(videostab2_data));
+       data->stab = calloc( 1, sizeof(StabData) );
+       data->trans = calloc( 1, sizeof (TransformData) ) ;
+       if ( data )
        {
                mlt_filter parent = mlt_filter_new();
-               parent->child = self;
+
+               parent->child = data;
                parent->close = filter_close;
                parent->process = filter_process;
-               self->parent = parent;
+               data->parent = parent;
                //properties for stabilize
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "shakiness", "4" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "accuracy", "4" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "stepsize", "6" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "algo", "1" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "mincontrast", "0.3" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "show", "0" ); 
-               
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "shakiness", "4" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "accuracy", "4" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "stepsize", "6" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "algo", "1" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "mincontrast", "0.3" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "show", "0" );
+
                //properties for transform
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "smoothing", "10" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "maxshift", "-1" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "maxangle", "-1" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "crop", "0" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "invert", "0" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "relative", "1" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "zoom", "0" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "optzoom", "1" ); 
-               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "sharpen", "0.8" ); 
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "smoothing", "10" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "maxshift", "-1" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "maxangle", "-1" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "crop", "0" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "invert", "0" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "relative", "1" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "zoom", "0" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "optzoom", "1" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES(parent), "sharpen", "0.8" );
                return parent;
        }
        return NULL;
index c61f3aa5d3091bb699f16aa883745d5d86da4da3..31a4204dfe03d8b2822e7b07fb5afb25e443c33b 100644 (file)
@@ -6,25 +6,25 @@
  *  mlt adaption by Marco Gittler marco at gitma dot de 2011
  *
  *  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. 
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
 
 /* Typical call:
- *  transcode -V -J stabilize=shakiness=5:show=1,preview 
+ *  transcode -V -J stabilize=shakiness=5:show=1,preview
  *         -i inp.mpeg -y null,null -o dummy
  *  all parameters are optional
 */
@@ -49,7 +49,7 @@
     TC_MODULE_FLAG_RECONFIGURABLE | TC_MODULE_FLAG_DELAY
 #define MAX(a,b)         ((a < b) ?  (b) : (a))
 #define MIN(a,b)         ((a < b) ?  (a) : (b))
-#include "stabilize.h"  
+#include "stabilize.h"
 #include <stdlib.h>
 #include <string.h>
 #include <framework/mlt_types.h>
@@ -69,7 +69,7 @@ void addTrans(StabData* sd, Transform sl)
 
 
 /** initialise measurement fields on the frame.
-    The size of the fields and the maxshift is used to 
+    The size of the fields and the maxshift is used to
     calculate an optimal distribution in the frame.
 */
 int initFields(StabData* sd)
@@ -80,7 +80,7 @@ int initFields(StabData* sd)
     // make sure that the remaining rows have the same length
     sd->field_num  = rows*cols;
     sd->field_rows = rows;
-    mlt_log_debug (NULL,"field setup: rows: %i cols: %i Total: %i fields", 
+    mlt_log_debug (NULL,"field setup: rows: %i cols: %i Total: %i fields",
                 rows, cols, sd->field_num);
 
     if (!(sd->fields = malloc(sizeof(Field) * sd->field_num))) {
@@ -112,13 +112,13 @@ int initFields(StabData* sd)
    \param d_x shift in x direction
    \param d_y shift in y direction
 */
-double compareImg(unsigned char* I1, unsigned char* I2, 
+double compareImg(unsigned char* I1, unsigned char* I2,
                   int width, int height,  int bytesPerPixel, int d_x, int d_y)
 {
     int i, j;
     unsigned char* p1 = NULL;
     unsigned char* p2 = NULL;
-    long int sum = 0;  
+    long int sum = 0;
     int effectWidth = width - abs(d_x);
     int effectHeight = height - abs(d_y);
 
@@ -134,26 +134,26 @@ double compareImg(unsigned char* I1, unsigned char* I2,
     for (i = 0; i < effectHeight; i++) {
         p1 = I1;
         p2 = I2;
-        if (d_y > 0 ){ 
+        if (d_y > 0 ){
             p1 += (i + d_y) * width * bytesPerPixel;
             p2 += i * width * bytesPerPixel;
         } else {
             p1 += i * width * bytesPerPixel;
             p2 += (i - d_y) * width * bytesPerPixel;
         }
-        if (d_x > 0) { 
+        if (d_x > 0) {
             p1 += d_x * bytesPerPixel;
         } else {
-            p2 -= d_x * bytesPerPixel; 
+            p2 -= d_x * bytesPerPixel;
         }
 #ifdef USE_SSE2
                __m128i A,B,C,D,E;
                for (j = 0; j < effectWidth * bytesPerPixel - 16; j++) {
 #else
                for (j = 0; j < effectWidth * bytesPerPixel; j++) {
-#endif 
+#endif
             /* fwrite(p1,1,1,pic1);fwrite(p1,1,1,pic1);fwrite(p1,1,1,pic1);
-               fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2); 
+               fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2);
              */
 #ifdef USE_SSE2
                        A= _mm_loadu_si128((__m128i*)p1); //load unaligned data
@@ -162,35 +162,35 @@ double compareImg(unsigned char* I1, unsigned char* I2,
                        D = _mm_srli_si128(C, 8); // shift first 64 byte value to align at the same as C
                        E = _mm_add_epi32(C, D); // add the 2 values (sum of all diffs)
                        sum+= _mm_cvtsi128_si32(E); //convert _m128i to int
-                       
+
             p1+=16;
-            p2+=16;     
+            p2+=16;
                        j+=15;
 #else
             sum += abs((int)*p1 - (int)*p2);
             p1++;
-            p2++;      
+            p2++;
 #endif
         }
     }
     /*  fclose(pic1);
-        fclose(pic2); 
+        fclose(pic2);
      */
     return sum/((double) effectWidth * effectHeight * bytesPerPixel);
 }
 
 /**
-   compares a small part of two given images 
+   compares a small part of two given images
    and returns the average absolute difference.
-   Field center, size and shift have to be choosen, 
+   Field center, size and shift have to be choosen,
    so that no clipping is required
-     
-   \param field Field specifies position(center) and size of subimage 
+
+   \param field Field specifies position(center) and size of subimage
    \param d_x shift in x direction
-   \param d_y shift in y direction   
+   \param d_y shift in y direction
 */
-double compareSubImg(unsigned char* const I1, unsigned char* const I2, 
-                     const Field* field, 
+double compareSubImg(unsigned char* const I1, unsigned char* const I2,
+                     const Field* field,
                      int width, int height, int bytesPerPixel, int d_x, int d_y)
 {
     int k, j;
@@ -205,7 +205,7 @@ double compareSubImg(unsigned char* const I1, unsigned char* const I2,
     // TODO: use some mmx or sse stuff here
 #ifdef USE_SSE2
        __m128i A,B,C,D,E;
-#endif 
+#endif
     for (j = 0; j < field->size; j++){
 #ifdef USE_SSE2
                        for (k = 0; k < (field->size * bytesPerPixel) - 16 ; k++) {
@@ -215,15 +215,15 @@ double compareSubImg(unsigned char* const I1, unsigned char* const I2,
                                D = _mm_srli_si128(C, 8); // shift value 8 byte right
                                E = _mm_add_epi32(C, D); // add the 2 values (sum of all diffs)
                                sum+= _mm_cvtsi128_si32(E); //convert _m128i to int
-                       
+
             p1+=16;
-            p2+=16;     
+            p2+=16;
                        k+=15;
 #else
                        for (k = 0; k < (field->size * bytesPerPixel); k++) {
             sum += abs((int)*p1 - (int)*p2);
             p1++;
-            p2++;     
+            p2++;
 #endif
         }
         p1 += ((width - field->size) * bytesPerPixel);
@@ -237,27 +237,27 @@ double contrastSubImgYUV(StabData* sd, const Field* field){
     return contrastSubImg(sd->curr,field,sd->width,sd->height,1);
 }
 
-/** 
-    \see contrastSubImg three times called with bytesPerPixel=3 
-    for all channels   
+/**
+    \see contrastSubImg three times called with bytesPerPixel=3
+    for all channels
  */
 double contrastSubImgRGB(StabData* sd, const Field* field){
     unsigned char* const I = sd->curr;
-    return (  contrastSubImg(I,  field,sd->width,sd->height,3) 
+    return (  contrastSubImg(I,  field,sd->width,sd->height,3)
             + contrastSubImg(I+1,field,sd->width,sd->height,3)
             + contrastSubImg(I+2,field,sd->width,sd->height,3))/3;
 }
 
 /**
    calculates Michelson-contrast in the given small part of the given image
-     
-   \param I pointer to framebuffer 
-   \param field Field specifies position(center) and size of subimage 
+
+   \param I pointer to framebuffer
+   \param field Field specifies position(center) and size of subimage
    \param width width of frame
    \param height height of frame
    \param bytesPerPixel calc contrast for only for first channel
 */
-double contrastSubImg(unsigned char* const I, const Field* field, 
+double contrastSubImg(unsigned char* const I, const Field* field,
                      int width, int height, int bytesPerPixel)
 {
 #if USE_SSE2
@@ -327,23 +327,23 @@ Transform calcShiftRGBSimple(StabData* sd)
 {
     int x = 0, y = 0;
     int i, j;
-    double minerror = 1e20;  
+    double minerror = 1e20;
     for (i = -sd->maxshift; i <= sd->maxshift; i++) {
         for (j = -sd->maxshift; j <= sd->maxshift; j++) {
-            double error = compareImg(sd->curr, sd->prev, 
+            double error = compareImg(sd->curr, sd->prev,
                                       sd->width, sd->height, 3, i, j);
             if (error < minerror) {
                 minerror = error;
                 x = i;
                 y = j;
-           }   
+           }
         }
-    } 
+    }
     return new_transform(x, y, 0, 0, 0);
 }
 
 
-/** tries to register current frame onto previous frame. 
+/** tries to register current frame onto previous frame.
     (only the luminance is used)
     This is the most simple algorithm:
     shift images to all possible positions and calc summed error
@@ -363,17 +363,17 @@ Transform calcShiftYUVSimple(StabData* sd)
 #endif
 
     // we only use the luminance part of the image
-    Y_c  = sd->curr;  
+    Y_c  = sd->curr;
     //  Cb_c = sd->curr + sd->width*sd->height;
     //Cr_c = sd->curr + 5*sd->width*sd->height/4;
-    Y_p  = sd->prev;  
+    Y_p  = sd->prev;
     //Cb_p = sd->prev + sd->width*sd->height;
     //Cr_p = sd->prev + 5*sd->width*sd->height/4;
 
-    double minerror = 1e20;  
+    double minerror = 1e20;
     for (i = -sd->maxshift; i <= sd->maxshift; i++) {
         for (j = -sd->maxshift; j <= sd->maxshift; j++) {
-            double error = compareImg(Y_c, Y_p, 
+            double error = compareImg(Y_c, Y_p,
                                       sd->width, sd->height, 1, i, j);
 #ifdef STABVERBOSE
             fprintf(f, "%i %i %f\n", i, j, error);
@@ -382,9 +382,9 @@ Transform calcShiftYUVSimple(StabData* sd)
                 minerror = error;
                 x = i;
                 y = j;
-            }  
+            }
         }
-    }  
+    }
 #ifdef STABVERBOSE
     fclose(f);
     tc_log_msg(MOD_NAME, "Minerror: %f\n", minerror);
@@ -394,23 +394,23 @@ Transform calcShiftYUVSimple(StabData* sd)
 
 
 
-/* calculates rotation angle for the given transform and 
+/* calculates rotation angle for the given transform and
  * field with respect to the given center-point
  */
-double calcAngle(StabData* sd, Field* field, Transform* t, 
+double calcAngle(StabData* sd, Field* field, Transform* t,
                  int center_x, int center_y)
 {
-    // we better ignore fields that are to close to the rotation center 
+    // we better ignore fields that are to close to the rotation center
     if (abs(field->x - center_x) + abs(field->y - center_y) < sd->maxshift) {
         return 0;
     } else {
-        // double r = sqrt(field->x*field->x + field->y*field->y);   
+        // double r = sqrt(field->x*field->x + field->y*field->y);
         double a1 = atan2(field->y - center_y, field->x - center_x);
-        double a2 = atan2(field->y - center_y + t->y, 
+        double a2 = atan2(field->y - center_y + t->y,
                           field->x - center_x + t->x);
         double diff = a2 - a1;
-        return (diff>M_PI) ? diff - 2*M_PI 
-            : ( (diff<-M_PI) ? diff + 2*M_PI : diff);    
+        return (diff>M_PI) ? diff - 2*M_PI
+            : ( (diff<-M_PI) ? diff + 2*M_PI : diff);
     }
 }
 
@@ -432,28 +432,28 @@ Transform calcFieldTransYUV(StabData* sd, const Field* field, int fieldnum)
 /*         return t; */
 /*     } */
 #ifdef STABVERBOSE
-    // printf("%i %i %f\n", sd->t, fieldnum, contr);    
+    // printf("%i %i %f\n", sd->t, fieldnum, contr);
     FILE *f = NULL;
     char buffer[32];
     snprintf(buffer, sizeof(buffer), "f%04i_%02i.dat", sd->t, fieldnum);
     f = fopen(buffer, "w");
     fprintf(f, "# splot \"%s\"\n", buffer);
-#endif    
+#endif
 
-    double minerror = 1e10;  
+    double minerror = 1e10;
     double error = 1e10;
     for (i = -sd->maxshift; i <= sd->maxshift; i += sd->stepsize) {
         for (j = -sd->maxshift; j <= sd->maxshift; j += sd->stepsize) {
-            error = compareSubImg(Y_c, Y_p, field, 
+            error = compareSubImg(Y_c, Y_p, field,
                                          sd->width, sd->height, 1, i, j);
 #ifdef STABVERBOSE
             fprintf(f, "%i %i %f\n", i, j, error);
-#endif 
+#endif
             if (error < minerror) {
                 minerror = error;
                 t.x = i;
                 t.y = j;
-            }  
+            }
         }
     }
 
@@ -461,34 +461,34 @@ Transform calcFieldTransYUV(StabData* sd, const Field* field, int fieldnum)
         int r = sd->stepsize - 1;
         for (i = t.x - r; i <= t.x + r; i += 1) {
             for (j = -t.y - r; j <= t.y + r; j += 1) {
-                if (i == t.x && j == t.y) 
+                if (i == t.x && j == t.y)
                     continue; //no need to check this since already done
-                error = compareSubImg(Y_c, Y_p, field, 
+                error = compareSubImg(Y_c, Y_p, field,
                                       sd->width, sd->height, 1, i, j);
 #ifdef STABVERBOSE
                 fprintf(f, "%i %i %f\n", i, j, error);
-#endif         
+#endif
                 if (error < minerror){
                     minerror = error;
                     t.x = i;
                     t.y = j;
-                }      
+                }
             }
         }
     }
-#ifdef STABVERBOSE 
-    fclose(f); 
+#ifdef STABVERBOSE
+    fclose(f);
     mlt_log_debug ( "Minerror: %f\n", minerror);
 #endif
 
     if (!sd->allowmax && fabs(t.x) == sd->maxshift) {
-#ifdef STABVERBOSE 
+#ifdef STABVERBOSE
         mlt_log_debug ( "maximal x shift ");
 #endif
         t.x = 0;
     }
     if (!sd->allowmax && fabs(t.y) == sd->maxshift) {
-#ifdef STABVERBOSE 
+#ifdef STABVERBOSE
         mlt_log_debug ("maximal y shift ");
 #endif
         t.y = 0;
@@ -496,7 +496,7 @@ Transform calcFieldTransYUV(StabData* sd, const Field* field, int fieldnum)
     return t;
 }
 
-/* calculates the optimal transformation for one field in RGB 
+/* calculates the optimal transformation for one field in RGB
  *   slower than the YUV version because it uses all three color channels
  */
 Transform calcFieldTransRGB(StabData* sd, const Field* field, int fieldnum)
@@ -504,28 +504,28 @@ Transform calcFieldTransRGB(StabData* sd, const Field* field, int fieldnum)
     Transform t = null_transform();
     unsigned char *I_c = sd->curr, *I_p = sd->prev;
     int i, j;
-  
-    double minerror = 1e20;  
+
+    double minerror = 1e20;
     for (i = -sd->maxshift; i <= sd->maxshift; i += 2) {
-        for (j=-sd->maxshift; j <= sd->maxshift; j += 2) {      
-            double error = compareSubImg(I_c, I_p, field, 
+        for (j=-sd->maxshift; j <= sd->maxshift; j += 2) {
+            double error = compareSubImg(I_c, I_p, field,
                                          sd->width, sd->height, 3, i, j);
             if (error < minerror) {
                 minerror = error;
                 t.x = i;
                 t.y = j;
-            }  
+            }
         }
     }
     for (i = t.x - 1; i <= t.x + 1; i += 2) {
         for (j = -t.y - 1; j <= t.y + 1; j += 2) {
-            double error = compareSubImg(I_c, I_p, field, 
+            double error = compareSubImg(I_c, I_p, field,
                                          sd->width, sd->height, 3, i, j);
             if (error < minerror) {
                 minerror = error;
                 t.x = i;
                 t.y = j;
-            }  
+            }
         }
     }
     if (!sd->allowmax && fabs(t.x) == sd->maxshift) {
@@ -537,8 +537,8 @@ Transform calcFieldTransRGB(StabData* sd, const Field* field, int fieldnum)
     return t;
 }
 
-/* compares contrast_idx structures respect to the contrast 
-   (for sort function) 
+/* compares contrast_idx structures respect to the contrast
+   (for sort function)
 */
 int cmp_contrast_idx(const void *ci1, const void* ci2)
 {
@@ -556,7 +556,7 @@ tlist* selectfields(StabData* sd, contrastSubImgFunc contrastfunc)
     int i,j;
     tlist* goodflds = tlist_new(0);
     contrast_idx *ci = malloc(sizeof(contrast_idx) * sd->field_num);
-    
+
     // we split all fields into row+1 segments and take from each segment
     // the best fields
     int numsegms = (sd->field_rows+1);
@@ -565,12 +565,12 @@ tlist* selectfields(StabData* sd, contrastSubImgFunc contrastfunc)
     contrast_idx *ci_segms = malloc(sizeof(contrast_idx) * sd->field_num);
     int remaining   = 0;
     // calculate contrast for each field
-    for (i = 0; i < sd->field_num; i++) {        
+    for (i = 0; i < sd->field_num; i++) {
         ci[i].contrast = contrastfunc(sd, &sd->fields[i]);
         ci[i].index=i;
         if(ci[i].contrast < sd->contrast_threshold) ci[i].contrast = 0;
         // else printf("%i %lf\n", ci[i].index, ci[i].contrast);
-    }   
+    }
 
     memcpy(ci_segms, ci, sizeof(contrast_idx) * sd->field_num);
     // get best fields from each segment
@@ -581,33 +581,33 @@ tlist* selectfields(StabData* sd, contrastSubImgFunc contrastfunc)
         //printf("Segment: %i: %i-%i\n", i, startindex, endindex);
 
         // sort within segment
-        qsort(ci_segms+startindex, endindex-startindex, 
-              sizeof(contrast_idx), cmp_contrast_idx);        
+        qsort(ci_segms+startindex, endindex-startindex,
+              sizeof(contrast_idx), cmp_contrast_idx);
         // take maxfields/numsegms
         for(j=0; j<sd->maxfields/numsegms; j++){
             if(startindex+j >= endindex) continue;
-            // printf("%i %lf\n", ci_segms[startindex+j].index, 
+            // printf("%i %lf\n", ci_segms[startindex+j].index,
             //                    ci_segms[startindex+j].contrast);
-            if(ci_segms[startindex+j].contrast > 0){                
+            if(ci_segms[startindex+j].contrast > 0){
                tlist_append(goodflds, &ci[ci_segms[startindex+j].index],sizeof(contrast_idx));
                 // don't consider them in the later selection process
-                ci_segms[startindex+j].contrast=0; 
-            }                                                     
+                ci_segms[startindex+j].contrast=0;
+            }
         }
     }
     // check whether enough fields are selected
     // printf("Phase2: %i\n", tc_list_size(goodflds));
-    remaining = sd->maxfields - tlist_size(goodflds); 
+    remaining = sd->maxfields - tlist_size(goodflds);
     if(remaining > 0){
         // take the remaining from the leftovers
-        qsort(ci_segms, sd->field_num,                   
+        qsort(ci_segms, sd->field_num,
               sizeof(contrast_idx), cmp_contrast_idx);
         for(j=0; j < remaining; j++){
             if(ci_segms[j].contrast > 0){
-                tlist_append(goodflds, &ci_segms[j], sizeof(contrast_idx));                    
-            }                                                     
+                tlist_append(goodflds, &ci_segms[j], sizeof(contrast_idx));
+            }
         }
-    }     
+    }
     // printf("Ende: %i\n", tc_list_size(goodflds));
     free(ci);
     free(ci_segms);
@@ -616,11 +616,11 @@ tlist* selectfields(StabData* sd, contrastSubImgFunc contrastfunc)
 
 
 
-/* tries to register current frame onto previous frame. 
+/* tries to register current frame onto previous frame.
  *   Algorithm:
  *   check all fields for vertical and horizontal transformation
  *   use minimal difference of all possible positions
- *   discards fields with low contrast 
+ *   discards fields with low contrast
  *   select maxfields field according to their contrast
  *   calculate shift as cleaned mean of all remaining fields
  *   calculate rotation angle of each field in respect to center of fields
@@ -643,17 +643,17 @@ Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc,
     f = fopen(buffer, "w");
     fprintf(f, "# plot \"%s\" w l, \"\" every 2:1:0\n", buffer);
 #endif
-    
+
 
     tlist* goodflds = selectfields(sd, contrastfunc);
 
-    // use all "good" fields and calculate optimal match to previous frame 
+    // use all "good" fields and calculate optimal match to previous frame
     contrast_idx* f;
     while((f = (contrast_idx*)tlist_pop(goodflds,0) ) != 0){
         int i = f->index;
         t =  fieldfunc(sd, &sd->fields[i], i); // e.g. calcFieldTransYUV
 #ifdef STABVERBOSE
-        fprintf(f, "%i %i\n%f %f %i\n \n\n", sd->fields[i].x, sd->fields[i].y, 
+        fprintf(f, "%i %i\n%f %f %i\n \n\n", sd->fields[i].x, sd->fields[i].y,
                 sd->fields[i].x + t.x, sd->fields[i].y + t.y, t.extra);
 #endif
         if (t.extra != -1){ // ignore if extra == -1 (unused at the moment)
@@ -665,37 +665,37 @@ Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc,
     tlist_fini(goodflds);
 
     t = null_transform();
-    num_trans = index; // amount of transforms we actually have    
+    num_trans = index; // amount of transforms we actually have
     if (num_trans < 1) {
         printf( "too low contrast! No field remains.\n \
                     (no translations are detected in frame %i)", sd->t);
         return t;
     }
-        
+
     int center_x = 0;
     int center_y = 0;
     // calc center point of all remaining fields
     for (i = 0; i < num_trans; i++) {
         center_x += fs[i]->x;
-        center_y += fs[i]->y;            
-    } 
+        center_y += fs[i]->y;
+    }
     center_x /= num_trans;
-    center_y /= num_trans;        
-    
+    center_y /= num_trans;
+
     if (sd->show){ // draw fields and transforms into frame.
-        // this has to be done one after another to handle possible overlap 
+        // this has to be done one after another to handle possible overlap
         if (sd->show > 1) {
             for (i = 0; i < num_trans; i++)
-                drawFieldScanArea(sd, fs[i], &ts[i]);            
+                drawFieldScanArea(sd, fs[i], &ts[i]);
         }
         for (i = 0; i < num_trans; i++)
-            drawField(sd, fs[i], &ts[i]);            
+            drawField(sd, fs[i], &ts[i]);
         for (i = 0; i < num_trans; i++)
-            drawFieldTrans(sd, fs[i], &ts[i]);            
-    } 
+            drawFieldTrans(sd, fs[i], &ts[i]);
+    }
     /* median over all transforms
        t= median_xy_transform(ts, sd->field_num);*/
-    // cleaned mean    
+    // cleaned mean
     t = cleanmean_xy_transform(ts, num_trans);
 
     // substract avg
@@ -705,8 +705,8 @@ Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc,
     // figure out angle
     if (sd->field_num < 6) {
         // the angle calculation is inaccurate for 5 and less fields
-        t.alpha = 0; 
-    } else {      
+        t.alpha = 0;
+    } else {
         for (i = 0; i < num_trans; i++) {
             angles[i] = calcAngle(sd, fs[i], &ts[i], center_x, center_y);
         }
@@ -714,7 +714,7 @@ Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc,
         t.alpha = -cleanmean(angles, num_trans, &min, &max);
         if(max-min>sd->maxanglevariation){
             t.alpha=0;
-            printf( "too large variation in angle(%f)\n", 
+            printf( "too large variation in angle(%f)\n",
                         max-min);
         }
     }
@@ -723,8 +723,8 @@ Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc,
     double p_x = (center_x - sd->width/2);
     double p_y = (center_y - sd->height/2);
     t.x += (cos(t.alpha)-1)*p_x  - sin(t.alpha)*p_y;
-    t.y += sin(t.alpha)*p_x  + (cos(t.alpha)-1)*p_y;    
-    
+    t.y += sin(t.alpha)*p_x  + (cos(t.alpha)-1)*p_y;
+
 #ifdef STABVERBOSE
     fclose(f);
 #endif
@@ -738,8 +738,8 @@ void drawFieldScanArea(StabData* sd, const Field* field, const Transform* t)
                mlt_log_warning (NULL, "format not usable\n");
         return;
        }
-    drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y, 
-            field->size+2*sd->maxshift, field->size+2*sd->maxshift, 80);   
+    drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y,
+            field->size+2*sd->maxshift, field->size+2*sd->maxshift, 80);
 }
 
 /** draws the field */
@@ -749,7 +749,7 @@ void drawField(StabData* sd, const Field* field, const Transform* t)
                mlt_log_warning (NULL, "format not usable\n");
         return;
        }
-    drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y, 
+    drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y,
             field->size, field->size, t->extra == -1 ? 100 : 40);
 }
 
@@ -760,20 +760,20 @@ void drawFieldTrans(StabData* sd, const Field* field, const Transform* t)
                mlt_log_warning (NULL, "format not usable\n");
         return;
        }
-    drawBox(sd->curr, sd->width, sd->height, 1, 
+    drawBox(sd->curr, sd->width, sd->height, 1,
             field->x, field->y, 5, 5, 128);     // draw center
-    drawBox(sd->curr, sd->width, sd->height, 1, 
+    drawBox(sd->curr, sd->width, sd->height, 1,
             field->x + t->x, field->y + t->y, 8, 8, 250); // draw translation
 }
 
 /**
  * draws a box at the given position x,y (center) in the given color
-   (the same for all channels) 
+   (the same for all channels)
  */
-void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, 
+void drawBox(unsigned char* I, int width, int height, int bytesPerPixel,
              int x, int y, int sizex, int sizey, unsigned char color){
-    
-    unsigned char* p = NULL;     
+
+    unsigned char* p = NULL;
     int j,k;
     p = I + ((x - sizex/2) + (y - sizey/2)*width)*bytesPerPixel;
     for (j = 0; j < sizey; j++){
@@ -803,8 +803,7 @@ struct iterdata {
 int stabilize_init(StabData* instance)
 {
 
-    instance = malloc(sizeof(StabData)); // allocation with zero values
-       memset(instance,sizeof(StabData),0);
+    instance = calloc(1,sizeof(StabData)); // allocation with zero values
     if (!instance) {
         return -1;
     }
@@ -821,11 +820,13 @@ int stabilize_configure(StabData* instance
                                /*TCModuleExtraData *xdata[]*/)
 {
     StabData *sd = instance;
-    /*    sd->framesize = sd->vob->im_v_width * MAX_PLANES * 
+    /*    sd->framesize = sd->vob->im_v_width * MAX_PLANES *
           sizeof(char) * 2 * sd->vob->im_v_height * 2;     */
     /*TODO sd->framesize = sd->vob->im_v_size;    */
-    sd->prev = calloc(1,sd->framesize);    
-    if (!sd->prev) {
+    sd->prev = calloc(1,sd->framesize);
+               sd->grayimage = calloc(1,sd->width*sd->height);
+
+    if (!sd->prev || !sd->grayimage) {
         printf( "malloc failed");
         return -1;
     }
@@ -835,7 +836,7 @@ int stabilize_configure(StabData* instance
     sd->allowmax   = 0;
     sd->field_size  = MIN(sd->width, sd->height)/12;
     sd->maxanglevariation = 1;
-    
+
     sd->shakiness = MIN(10,MAX(1,sd->shakiness));
     sd->accuracy  = MAX(sd->shakiness,MIN(15,MAX(1,sd->accuracy)));
     if (1) {
@@ -854,10 +855,10 @@ int stabilize_configure(StabData* instance
     // shift and size: shakiness 1: height/40; 10: height/4
     sd->maxshift    = MIN(sd->width, sd->height)*sd->shakiness/40;
     sd->field_size   = MIN(sd->width, sd->height)*sd->shakiness/40;
-  
-    mlt_log_debug ( NULL,  "Fieldsize: %i, Maximal translation: %i pixel\n", 
+
+    mlt_log_debug ( NULL,  "Fieldsize: %i, Maximal translation: %i pixel\n",
                 sd->field_size, sd->maxshift);
-    if (sd->algo==1) {        
+    if (sd->algo==1) {
         // initialize measurement fields. field_num is set here.
         if (!initFields(sd)) {
             return -1;
@@ -867,14 +868,13 @@ int stabilize_configure(StabData* instance
                     sd->maxfields, sd->field_num);
     }
     if (sd->show){
-        sd->currcopy = malloc(sd->framesize);
-               memset ( sd->currcopy, sd->framesize, 0 );
+        sd->currcopy = calloc(1,sd->framesize);
        }
 
     /* load unsharp filter to smooth the frames. This allows larger stepsize.*/
     char unsharp_param[128];
     int masksize = MIN(13,sd->stepsize*1.8); // only works up to 13.
-    sprintf(unsharp_param,"luma=-1:luma_matrix=%ix%i:pre=1", 
+    sprintf(unsharp_param,"luma=-1:luma_matrix=%ix%i:pre=1",
             masksize, masksize);
     return 0;
 }
@@ -885,16 +885,27 @@ int stabilize_configure(StabData* instance
  * See tcmodule-data.h for function details.
  */
 
-int stabilize_filter_video(StabData* instance, 
+int stabilize_filter_video(StabData* instance,
                                   unsigned char *frame,mlt_image_format pixelformat)
 {
     StabData *sd = instance;
-       sd->pixelformat=pixelformat; 
-
-    if(sd->show)  // save the buffer to restore at the end for prev
-        memcpy(sd->currcopy, frame, sd->framesize);
+    sd->pixelformat=pixelformat;
+               int l=sd->width*sd->height;
+               unsigned char* tmpgray=sd->grayimage;
+               if (pixelformat == mlt_image_yuv422){
+                       while(l--){
+                               *tmpgray++=*frame++;
+                               frame++;
+                       };
+               }
+
+    if(sd->show) { // save the buffer to restore at the end for prev
+                       if (pixelformat == mlt_image_yuv420p){
+                               memcpy(sd->currcopy, sd->grayimage, sd->framesize);
+                       }
+               }
     if (sd->hasSeenOneFrame) {
-        sd->curr = frame;
+        sd->curr = sd->grayimage;
         if (pixelformat == mlt_image_rgb24) {
             if (sd->algo == 0)
                 addTrans(sd, calcShiftRGBSimple(sd));
@@ -907,6 +918,12 @@ int stabilize_filter_video(StabData* instance,
             else if (sd->algo == 1)
                 addTrans(sd, calcTransFields(sd, calcFieldTransYUV,
                                              contrastSubImgYUV));
+        } else if (pixelformat == mlt_image_yuv422 ) {
+            if (sd->algo == 0)
+                addTrans(sd, calcShiftYUVSimple(sd));
+            else if (sd->algo == 1)
+                addTrans(sd, calcTransFields(sd, calcFieldTransYUV,
+                                             contrastSubImgYUV));
         } else {
             mlt_log_warning (NULL,"unsupported Codec: %i\n",
                         pixelformat);
@@ -916,9 +933,9 @@ int stabilize_filter_video(StabData* instance,
         sd->hasSeenOneFrame = 1;
         addTrans(sd, null_transform());
     }
-    
+
     if(!sd->show) { // copy current frame to prev for next frame comparison
-        memcpy(sd->prev, frame, sd->framesize);
+        memcpy(sd->prev, sd->grayimage, sd->framesize);
     } else { // use the copy because we changed the original frame
         memcpy(sd->prev, sd->currcopy, sd->framesize);
     }
@@ -938,6 +955,11 @@ int stabilize_stop(StabData* instance)
         free(sd->prev);
         sd->prev = NULL;
     }
+    if (sd->grayimage){
+                       free(sd->grayimage);
+                       sd->grayimage=NULL;
+
+               }
     return 0;
 }
 
index fd95e59ee53b02a275b001d89fc269aade28b9c1..520a1f75f58b0c16d2a27076d00598e99388e2c9 100644 (file)
@@ -79,6 +79,7 @@ typedef struct _stab_data {
     unsigned char* curr; // current frame buffer (only pointer)
     unsigned char* currcopy; // copy of the current frame needed for drawing
     unsigned char* prev; // frame buffer for last frame (copied)
+    unsigned char* grayimage; // frame buffer for last frame (copied)
     short hasSeenOneFrame; // true if we have a valid previous frame
 
     int width, height;
@@ -86,7 +87,6 @@ typedef struct _stab_data {
 
     /* list of transforms*/
     //TCList* transs;
-       void* parent;
     tlist* transs;
 
     Field* fields;
@@ -115,7 +115,6 @@ typedef struct _stab_data {
     int t;
 
     char conf_str[1024];
-       int initialized;
 } StabData;
 
 /* type for a function that calculates the transformation of a certain field 
index 11b133f5b69cd2723309e5ea73ef8813777b6007..176742dceee68b41395ecfcf6213381a04a09482 100644 (file)
@@ -2,23 +2,23 @@
  *  filter_transform.c
  *
  *  Copyright (C) Georg Martius - June 2007
- *   georg dot martius at web dot de  
+ *   georg dot martius at web dot de
  *
  *  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. 
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * Typical call:
  * transcode -J transform -i inp.mpeg -y xdiv,tcaud inp_stab.avi
 static const char* interpoltypes[5] = {"No (0)", "Linear (1)", "Bi-Linear (2)",
                                        "Quadratic (3)", "Bi-Cubic (4)"};
 
-void (*interpolate)(unsigned char *rv, float x, float y, 
-                    unsigned char* img, int width, int height, 
-                    unsigned char def) = 0;
+void (*interpolate)(unsigned char *rv, float x, float y,
+                    unsigned char* img, int width, int height,
+                    unsigned char def,unsigned char N, unsigned char channel) = 0;
 
 /** interpolateBiLinBorder: bi-linear interpolation function that also works at the border.
     This is used by many other interpolation methods at and outsize the border, see interpolate */
-void interpolateBiLinBorder(unsigned char *rv, float x, float y, 
-                            unsigned char* img, int width, int height, 
-                            unsigned char def)
+void interpolateBiLinBorder(unsigned char *rv, float x, float y,
+                            unsigned char* img, int width, int height,
+                            unsigned char def,unsigned char N, unsigned char channel)
 {
     int x_f = myfloor(x);
     int x_c = x_f+1;
     int y_f = myfloor(y);
     int y_c = y_f+1;
-    short v1 = PIXEL(img, x_c, y_c, width, height, def);
-    short v2 = PIXEL(img, x_c, y_f, width, height, def);
-    short v3 = PIXEL(img, x_f, y_c, width, height, def);
-    short v4 = PIXEL(img, x_f, y_f, width, height, def);        
-    float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) + 
+    short v1 = PIXELN(img, x_c, y_c, width, height, N, channel, def);
+    short v2 = PIXELN(img, x_c, y_f, width, height, N, channel, def);
+    short v3 = PIXELN(img, x_f, y_c, width, height, N, channel, def);
+    short v4 = PIXELN(img, x_f, y_f, width, height, N, channel, def);
+    float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) +
         (v2*(x - x_f) + v4*(x_c - x))*(y_c - y);
     *rv = (unsigned char)s;
 }
 
 /* taken from http://en.wikipedia.org/wiki/Bicubic_interpolation for alpha=-0.5
-   in matrix notation: 
+   in matrix notation:
    a0-a3 are the neigthboring points where the target point is between a1 and a2
    t is the point of interpolation (position between a1 and a2) value between 0 and 1
                  | 0, 2, 0, 0 |  |a0|
                  |-1, 0, 1, 0 |  |a1|
    (1,t,t^2,t^3) | 2,-5, 4,-1 |  |a2|
-                 |-1, 3,-3, 1 |  |a3|              
+                 |-1, 3,-3, 1 |  |a3|
 */
-static short bicub_kernel(float t, short a0, short a1, short a2, short a3){ 
+static short bicub_kernel(float t, short a0, short a1, short a2, short a3){
     return (2*a1 + t*((-a0+a2) + t*((2*a0-5*a1+4*a2-a3) + t*(-a0+3*a1-3*a2+a3) )) ) / 2;
 }
 
 /** interpolateBiCub: bi-cubic interpolation function using 4x4 pixel, see interpolate */
-void interpolateBiCub(unsigned char *rv, float x, float y, 
-                      unsigned char* img, int width, int height, unsigned char def)
+void interpolateBiCub(unsigned char *rv, float x, float y,
+                      unsigned char* img, int width, int height, unsigned char def,unsigned char N, unsigned char channel)
 {
     // do a simple linear interpolation at the border
-    if (x < 1 || x > width-2 || y < 1 || y > height - 2) { 
-        interpolateBiLinBorder(rv, x,y,img,width,height,def);    
+    if (x < 1 || x > width-2 || y < 1 || y > height - 2) {
+        interpolateBiLinBorder(rv, x,y,img,width,height,def,N,channel);
     } else {
         int x_f = myfloor(x);
         int y_f = myfloor(y);
         float tx = x-x_f;
         short v1 = bicub_kernel(tx,
-                                PIX(img, x_f-1, y_f-1, width, height),
-                                PIX(img, x_f,   y_f-1, width, height),
-                                PIX(img, x_f+1, y_f-1, width, height),
-                                PIX(img, x_f+2, y_f-1, width, height));
+                                PIXN(img, x_f-1, y_f-1, width, height, N, channel),
+                                PIXN(img, x_f,   y_f-1, width, height, N, channel),
+                                PIXN(img, x_f+1, y_f-1, width, height, N, channel),
+                                PIXN(img, x_f+2, y_f-1, width, height, N, channel));
         short v2 = bicub_kernel(tx,
-                                PIX(img, x_f-1, y_f, width, height),
-                                PIX(img, x_f,   y_f, width, height),
-                                PIX(img, x_f+1, y_f, width, height),
-                                PIX(img, x_f+2, y_f, width, height));
+                                PIXN(img, x_f-1, y_f, width, height, N, channel),
+                                PIXN(img, x_f,   y_f, width, height, N, channel),
+                                PIXN(img, x_f+1, y_f, width, height, N, channel),
+                                PIXN(img, x_f+2, y_f, width, height, N, channel));
         short v3 = bicub_kernel(tx,
-                                PIX(img, x_f-1, y_f+1, width, height),
-                                PIX(img, x_f,   y_f+1, width, height),
-                                PIX(img, x_f+1, y_f+1, width, height),
-                                PIX(img, x_f+2, y_f+1, width, height));
+                                PIXN(img, x_f-1, y_f+1, width, height, N, channel),
+                                PIXN(img, x_f,   y_f+1, width, height, N, channel),
+                                PIXN(img, x_f+1, y_f+1, width, height, N, channel),
+                                PIXN(img, x_f+2, y_f+1, width, height, N, channel));
         short v4 = bicub_kernel(tx,
-                                PIX(img, x_f-1, y_f+2, width, height),
-                                PIX(img, x_f,   y_f+2, width, height),
-                                PIX(img, x_f+1, y_f+2, width, height),
-                                PIX(img, x_f+2, y_f+2, width, height));
+                                PIXN(img, x_f-1, y_f+2, width, height, N, channel),
+                                PIXN(img, x_f,   y_f+2, width, height, N, channel),
+                                PIXN(img, x_f+1, y_f+2, width, height, N, channel),
+                                PIXN(img, x_f+2, y_f+2, width, height, N, channel));
         *rv = (unsigned char)bicub_kernel(y-y_f, v1, v2, v3, v4);
     }
 }
 
 /** interpolateSqr: bi-quatratic interpolation function, see interpolate */
-void interpolateSqr(unsigned char *rv, float x, float y, 
-                    unsigned char* img, int width, int height, unsigned char def)
+void interpolateSqr(unsigned char *rv, float x, float y,
+                    unsigned char* img, int width, int height, unsigned char def,unsigned char N, unsigned char channel)
 {
-    if (x < 0 || x > width-1 || y < 0 || y > height - 1) { 
-        interpolateBiLinBorder(rv, x, y, img, width, height, def);    
+    if (x < 0 || x > width-1 || y < 0 || y > height - 1) {
+        interpolateBiLinBorder(rv, x, y, img, width, height, def,N,channel);
     } else {
         int x_f = myfloor(x);
         int x_c = x_f+1;
         int y_f = myfloor(y);
         int y_c = y_f+1;
-        short v1 = PIX(img, x_c, y_c, width, height);
-        short v2 = PIX(img, x_c, y_f, width, height);
-        short v3 = PIX(img, x_f, y_c, width, height);
-        short v4 = PIX(img, x_f, y_f, width, height);
+        short v1 = PIXN(img, x_c, y_c, width, height, N, channel);
+        short v2 = PIXN(img, x_c, y_f, width, height, N, channel);
+        short v3 = PIXN(img, x_f, y_c, width, height, N, channel);
+        short v4 = PIXN(img, x_f, y_f, width, height, N, channel);
         float f1 = 1 - sqrt((x_c - x) * (y_c - y));
         float f2 = 1 - sqrt((x_c - x) * (y - y_f));
         float f3 = 1 - sqrt((x - x_f) * (y_c - y));
         float f4 = 1 - sqrt((x - x_f) * (y - y_f));
         float s  = (v1*f1 + v2*f2 + v3*f3+ v4*f4)/(f1 + f2 + f3 + f4);
-        *rv = (unsigned char)s;   
+        *rv = (unsigned char)s;
     }
 }
 
 /** interpolateBiLin: bi-linear interpolation function, see interpolate */
-void interpolateBiLin(unsigned char *rv, float x, float y, 
-                      unsigned char* img, int width, int height, 
-                      unsigned char def)
+void interpolateBiLin(unsigned char *rv, float x, float y,
+                      unsigned char* img, int width, int height,
+                      unsigned char def,unsigned char N, unsigned char channel)
 {
-    if (x < 0 || x > width-1 || y < 0 || y > height - 1) { 
-        interpolateBiLinBorder(rv, x, y, img, width, height, def);    
+    if (x < 0 || x > width-1 || y < 0 || y > height - 1) {
+        interpolateBiLinBorder(rv, x, y, img, width, height, def,N,channel);
     } else {
         int x_f = myfloor(x);
         int x_c = x_f+1;
         int y_f = myfloor(y);
         int y_c = y_f+1;
-        short v1 = PIX(img, x_c, y_c, width, height);
-        short v2 = PIX(img, x_c, y_f, width, height);
-        short v3 = PIX(img, x_f, y_c, width, height);
-        short v4 = PIX(img, x_f, y_f, width, height);        
-        float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) +  
+        short v1 = PIXN(img, x_c, y_c, width, height, N, channel);
+        short v2 = PIXN(img, x_c, y_f, width, height, N, channel);
+        short v3 = PIXN(img, x_f, y_c, width, height, N, channel);
+        short v4 = PIXN(img, x_f, y_f, width, height, N, channel);
+        float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) +
             (v2*(x - x_f) + v4*(x_c - x))*(y_c - y);
         *rv = (unsigned char)s;
     }
@@ -160,35 +160,35 @@ void interpolateBiLin(unsigned char *rv, float x, float y,
 
 
 /** interpolateLin: linear (only x) interpolation function, see interpolate */
-void interpolateLin(unsigned char *rv, float x, float y, 
-                    unsigned char* img, int width, int height, 
-                    unsigned char def)
+void interpolateLin(unsigned char *rv, float x, float y,
+                    unsigned char* img, int width, int height,
+                    unsigned char def,unsigned char N, unsigned char channel)
 {
     int x_f = myfloor(x);
     int x_c = x_f+1;
     int y_n = myround(y);
-    float v1 = PIXEL(img, x_c, y_n, width, height, def);
-    float v2 = PIXEL(img, x_f, y_n, width, height, def);
+    float v1 = PIXELN(img, x_c, y_n, width, height, def, N, channel);
+    float v2 = PIXELN(img, x_f, y_n, width, height, def, N, channel);
     float s  = v1*(x - x_f) + v2*(x_c - x);
     *rv = (unsigned char)s;
 }
 
 /** interpolateZero: nearest neighbor interpolation function, see interpolate */
-void interpolateZero(unsigned char *rv, float x, float y, 
-                   unsigned char* img, int width, int height, unsigned char def)
+void interpolateZero(unsigned char *rv, float x, float y,
+                   unsigned char* img, int width, int height, unsigned char def,unsigned char N, unsigned char channel)
 {
     int x_n = myround(x);
     int y_n = myround(y);
-    *rv = (unsigned char) PIXEL(img, x_n, y_n, width, height, def);
+    *rv = (unsigned char) PIXELN(img, x_n, y_n, width, height, def,N,channel);
 }
 
 
-/** 
- * interpolateN: Bi-linear interpolation function for N channel image. 
+/**
+ * interpolateN: Bi-linear interpolation function for N channel image.
  *
  * Parameters:
  *             rv: destination pixel (call by reference)
- *            x,y: the source coordinates in the image img. Note this 
+ *            x,y: the source coordinates in the image img. Note this
  *                 are real-value coordinates, that's why we interpolate
  *            img: source image
  *   width,height: dimension of image
@@ -197,13 +197,13 @@ void interpolateZero(unsigned char *rv, float x, float y,
  *            def: default value if coordinates are out of range
  * Return value:  None
  */
-void interpolateN(unsigned char *rv, float x, float y, 
-                  unsigned char* img, int width, int height, 
+void interpolateN(unsigned char *rv, float x, float y,
+                  unsigned char* img, int width, int height,
                   unsigned char N, unsigned char channel,
                   unsigned char def)
 {
     if (x < - 1 || x > width || y < -1 || y > height) {
-        *rv = def;    
+        *rv = def;
     } else {
         int x_f = myfloor(x);
         int x_c = x_f+1;
@@ -212,19 +212,19 @@ void interpolateN(unsigned char *rv, float x, float y,
         short v1 = PIXELN(img, x_c, y_c, width, height, N, channel, def);
         short v2 = PIXELN(img, x_c, y_f, width, height, N, channel, def);
         short v3 = PIXELN(img, x_f, y_c, width, height, N, channel, def);
-        short v4 = PIXELN(img, x_f, y_f, width, height, N, channel, def);        
-        float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) + 
+        short v4 = PIXELN(img, x_f, y_f, width, height, N, channel, def);
+        float s  = (v1*(x - x_f)+v3*(x_c - x))*(y - y_f) +
             (v2*(x - x_f) + v4*(x_c - x))*(y_c - y);
-        *rv = (unsigned char)s;        
+        *rv = (unsigned char)s;
     }
 }
 
 
-/** 
+/**
  * transformRGB: applies current transformation to frame
  * Parameters:
  *         td: private data structure of this filter
- * Return value: 
+ * Return value:
  *         0 for failture, 1 for success
  * Preconditions:
  *  The frame must be in RGB format
@@ -235,50 +235,53 @@ int transformRGB(TransformData* td)
     int x = 0, y = 0, z = 0;
     unsigned char *D_1, *D_2;
     t = td->trans[td->current_trans];
-  
-    D_1  = td->src;  
-    D_2  = td->dest;  
+
+    D_1  = td->src;
+    D_2  = td->dest;
+               float zm = 1.0-t.zoom/100;
+               float zcos_a = zm*cos(-t.alpha); // scaled cos
+    float zsin_a = zm*sin(-t.alpha); // scaled sin
     float c_s_x = td->width_src/2.0;
     float c_s_y = td->height_src/2.0;
     float c_d_x = td->width_dest/2.0;
-    float c_d_y = td->height_dest/2.0;    
+    float c_d_y = td->height_dest/2.0;
 
     /* for each pixel in the destination image we calc the source
-     * coordinate and make an interpolation: 
-     *      p_d = c_d + M(p_s - c_s) + t 
-     * where p are the points, c the center coordinate, 
-     *  _s source and _d destination, 
+     * coordinate and make an interpolation:
+     *      p_d = c_d + M(p_s - c_s) + t
+     * where p are the points, c the center coordinate,
+     *  _s source and _d destination,
      *  t the translation, and M the rotation matrix
      *      p_s = M^{-1}(p_d - c_d - t) + c_s
      */
     /* All 3 channels */
-    if (fabs(t.alpha) > td->rotation_threshhold) {
+    if (fabs(t.alpha) > td->rotation_threshhold || t.zoom != 0) {
         for (x = 0; x < td->width_dest; x++) {
             for (y = 0; y < td->height_dest; y++) {
                 float x_d1 = (x - c_d_x);
                 float y_d1 = (y - c_d_y);
-                float x_s  =  cos(-t.alpha) * x_d1 
-                    + sin(-t.alpha) * y_d1 + c_s_x -t.x;
-                float y_s  = -sin(-t.alpha) * x_d1 
-                    + cos(-t.alpha) * y_d1 + c_s_y -t.y;                
-                for (z = 0; z < 3; z++) { // iterate over colors 
+                float x_s  =  zcos_a * x_d1
+                    + zsin_a * y_d1 + c_s_x -t.x;
+                float y_s  = -zsin_a * x_d1
+                    + zcos_a * y_d1 + c_s_y -t.y;
+                for (z = 0; z < 3; z++) { // iterate over colors
                     unsigned char* dest = &D_2[(x + y * td->width_dest)*3+z];
-                    interpolateN(dest, x_s, y_s, D_1, 
-                                 td->width_src, td->height_src, 
+                    interpolateN(dest, myfloor(x_s), myfloor(y_s), D_1,
+                                 td->width_src, td->height_src,
                                  3, z, td->crop ? 16 : *dest);
                 }
             }
         }
-     }else { 
-        /* no rotation, just translation 
-         *(also no interpolation, since no size change (so far) 
+     }else {
+        /* no rotation, just translation
+         *(also no interpolation, since no size change (so far)
          */
         int round_tx = myround(t.x);
         int round_ty = myround(t.y);
         for (x = 0; x < td->width_dest; x++) {
             for (y = 0; y < td->height_dest; y++) {
                 for (z = 0; z < 3; z++) { // iterate over colors
-                    short p = PIXELN(D_1, x - round_tx, y - round_ty, 
+                    short p = PIXELN(D_1, x - round_tx, y - round_ty,
                                      td->width_src, td->height_src, 3, z, -1);
                     if (p == -1) {
                         if (td->crop == 1)
@@ -293,12 +296,12 @@ int transformRGB(TransformData* td)
     return 1;
 }
 
-/** 
+/**
  * transformYUV: applies current transformation to frame
  *
  * Parameters:
  *         td: private data structure of this filter
- * Return value: 
+ * Return value:
  *         0 for failture, 1 for success
  * Preconditions:
  *  The frame must be in YUV format
@@ -309,9 +312,9 @@ int transformYUV(TransformData* td)
     int x = 0, y = 0;
     unsigned char *Y_1, *Y_2, *Cb_1, *Cb_2, *Cr_1, *Cr_2;
     t = td->trans[td->current_trans];
-  
-    Y_1  = td->src;  
-    Y_2  = td->dest;  
+
+    Y_1  = td->src;
+    Y_2  = td->dest;
     Cb_1 = td->src + td->width_src * td->height_src;
     Cb_2 = td->dest + td->width_dest * td->height_dest;
     Cr_1 = td->src + 5*td->width_src * td->height_src/4;
@@ -319,17 +322,17 @@ int transformYUV(TransformData* td)
     float c_s_x = td->width_src/2.0;
     float c_s_y = td->height_src/2.0;
     float c_d_x = td->width_dest/2.0;
-    float c_d_y = td->height_dest/2.0;    
-    
+    float c_d_y = td->height_dest/2.0;
+
     float z = 1.0-t.zoom/100;
     float zcos_a = z*cos(-t.alpha); // scaled cos
     float zsin_a = z*sin(-t.alpha); // scaled sin
 
     /* for each pixel in the destination image we calc the source
-     * coordinate and make an interpolation: 
-     *      p_d = c_d + M(p_s - c_s) + t 
-     * where p are the points, c the center coordinate, 
-     *  _s source and _d destination, 
+     * coordinate and make an interpolation:
+     *      p_d = c_d + M(p_s - c_s) + t
+     * where p are the points, c the center coordinate,
+     *  _s source and _d destination,
      *  t the translation, and M the rotation and scaling matrix
      *      p_s = M^{-1}(p_d - c_d - t) + c_s
      */
@@ -339,25 +342,25 @@ int transformYUV(TransformData* td)
             for (y = 0; y < td->height_dest; y++) {
                 float x_d1 = (x - c_d_x);
                 float y_d1 = (y - c_d_y);
-                float x_s  =  zcos_a * x_d1 
+                float x_s  =  zcos_a * x_d1
                     + zsin_a * y_d1 + c_s_x -t.x;
-                float y_s  = -zsin_a * x_d1 
+                float y_s  = -zsin_a * x_d1
                     + zcos_a * y_d1 + c_s_y -t.y;
                 unsigned char* dest = &Y_2[x + y * td->width_dest];
-                interpolate(dest, x_s, y_s, Y_1, 
-                            td->width_src, td->height_src, 
-                            td->crop ? 16 : *dest);
+                interpolate(dest, x_s, y_s, Y_1,
+                            td->width_src, td->height_src,
+                            td->crop ? 16 : *dest,1,0);
             }
         }
-     }else { 
-        /* no rotation, no zooming, just translation 
-         *(also no interpolation, since no size change) 
+     }else {
+        /* no rotation, no zooming, just translation
+         *(also no interpolation, since no size change)
          */
         int round_tx = myround(t.x);
         int round_ty = myround(t.y);
         for (x = 0; x < td->width_dest; x++) {
             for (y = 0; y < td->height_dest; y++) {
-                short p = PIXEL(Y_1, x - round_tx, y - round_ty, 
+                short p = PIXEL(Y_1, x - round_tx, y - round_ty,
                                 td->width_src, td->height_src, -1);
                 if (p == -1) {
                     if (td->crop == 1)
@@ -379,29 +382,29 @@ int transformYUV(TransformData* td)
             for (y = 0; y < hd2; y++) {
                 float x_d1 = x - (c_d_x)/2;
                 float y_d1 = y - (c_d_y)/2;
-                float x_s  =  zcos_a * x_d1 
+                float x_s  =  zcos_a * x_d1
                     + zsin_a * y_d1 + (c_s_x -t.x)/2;
-                float y_s  = -zsin_a * x_d1 
+                float y_s  = -zsin_a * x_d1
                     + zcos_a * y_d1 + (c_s_y -t.y)/2;
                 unsigned char* dest = &Cr_2[x + y * wd2];
-                interpolate(dest, x_s, y_s, Cr_1, ws2, hs2, 
-                            td->crop ? 128 : *dest);
+                interpolate(dest, x_s, y_s, Cr_1, ws2, hs2,
+                            td->crop ? 128 : *dest,1,0);
                 dest = &Cb_2[x + y * wd2];
-                interpolate(dest, x_s, y_s, Cb_1, ws2, hs2, 
-                            td->crop ? 128 : *dest);           
+                interpolate(dest, x_s, y_s, Cb_1, ws2, hs2,
+                            td->crop ? 128 : *dest,1,0);
             }
         }
-    } else { // no rotation, no zoom, no interpolation, just translation 
+    } else { // no rotation, no zoom, no interpolation, just translation
         int round_tx2 = myround(t.x/2.0);
-        int round_ty2 = myround(t.y/2.0);        
+        int round_ty2 = myround(t.y/2.0);
         for (x = 0; x < wd2; x++) {
             for (y = 0; y < hd2; y++) {
-                short cr = PIXEL(Cr_1, x - round_tx2, y - round_ty2, 
+                short cr = PIXEL(Cr_1, x - round_tx2, y - round_ty2,
                                  wd2, hd2, -1);
-                short cb = PIXEL(Cb_1, x - round_tx2, y - round_ty2, 
+                short cb = PIXEL(Cb_1, x - round_tx2, y - round_ty2,
                                  wd2, hd2, -1);
                 if (cr == -1) {
-                    if (td->crop==1) { 
+                    if (td->crop==1) {
                         Cr_2[x + y * wd2] = 128;
                         Cb_2[x + y * wd2] = 128;
                     }
@@ -419,7 +422,7 @@ int transformYUV(TransformData* td)
 /**
  * preprocess_transforms: does smoothing, relative to absolute conversion,
  *  and cropping of too large transforms.
- *  This is actually the core algorithm for canceling the jiggle in the 
+ *  This is actually the core algorithm for canceling the jiggle in the
  *  movie. We perform a low-pass filter in terms of transformation size.
  *  This enables still camera movement, but in a smooth fasion.
  *
@@ -454,35 +457,35 @@ int preprocess_transforms(TransformData* td)
          */
         int s = td->smoothing * 2 + 1;
         Transform null = null_transform();
-        /* avg is the average over [-smoothing, smoothing] transforms 
+        /* avg is the average over [-smoothing, smoothing] transforms
            around the current point */
         Transform avg;
-        /* avg2 is a sliding average over the filtered signal! (only to past) 
+        /* avg2 is a sliding average over the filtered signal! (only to past)
          *  with smoothing * 10 horizont to kill offsets */
         Transform avg2 = null_transform();
         double tau = 1.0/(3 * s);
         /* initialise sliding sum with hypothetic sum centered around
          * -1st element. We have two choices:
-         * a) assume the camera is not moving at the beginning 
+         * a) assume the camera is not moving at the beginning
          * b) assume that the camera moves and we use the first transforms
          */
-        Transform s_sum = null; 
+        Transform s_sum = null;
         for (i = 0; i < td->smoothing; i++){
             s_sum = add_transforms(&s_sum, i < td->trans_len ? &ts2[i]:&null);
         }
         mult_transform(&s_sum, 2); // choice b (comment out for choice a)
 
         for (i = 0; i < td->trans_len; i++) {
-            Transform* old = ((i - td->smoothing - 1) < 0) 
+            Transform* old = ((i - td->smoothing - 1) < 0)
                 ? &null : &ts2[(i - td->smoothing - 1)];
-            Transform* new = ((i + td->smoothing) >= td->trans_len) 
+            Transform* new = ((i + td->smoothing) >= td->trans_len)
                 ? &null : &ts2[(i + td->smoothing)];
             s_sum = sub_transforms(&s_sum, old);
             s_sum = add_transforms(&s_sum, new);
 
             avg = mult_transform(&s_sum, 1.0/s);
 
-            /* lowpass filter: 
+            /* lowpass filter:
              * meaning high frequency must be transformed away
              */
             ts[i] = sub_transforms(&ts2[i], &avg);
@@ -492,35 +495,35 @@ int preprocess_transforms(TransformData* td)
             ts[i] = sub_transforms(&ts[i], &avg2);
 
             if (0 /*verbose*/ ) {
-                mlt_log_warning(NULL,"s_sum: %5lf %5lf %5lf, ts: %5lf, %5lf, %5lf\n", 
-                           s_sum.x, s_sum.y, s_sum.alpha, 
+                mlt_log_warning(NULL,"s_sum: %5lf %5lf %5lf, ts: %5lf, %5lf, %5lf\n",
+                           s_sum.x, s_sum.y, s_sum.alpha,
                            ts[i].x, ts[i].y, ts[i].alpha);
-                mlt_log_warning(NULL, 
-                           "  avg: %5lf, %5lf, %5lf avg2: %5lf, %5lf, %5lf", 
-                           avg.x, avg.y, avg.alpha, 
-                           avg2.x, avg2.y, avg2.alpha);      
+                mlt_log_warning(NULL,
+                           "  avg: %5lf, %5lf, %5lf avg2: %5lf, %5lf, %5lf",
+                           avg.x, avg.y, avg.alpha,
+                           avg2.x, avg2.y, avg2.alpha);
             }
         }
         free(ts2);
     }
-  
-  
+
+
     /*  invert? */
     if (td->invert) {
         for (i = 0; i < td->trans_len; i++) {
-            ts[i] = mult_transform(&ts[i], -1);      
+            ts[i] = mult_transform(&ts[i], -1);
         }
     }
-  
+
     /* relative to absolute */
     if (td->relative) {
         Transform t = ts[0];
         for (i = 1; i < td->trans_len; i++) {
             if (0/*verbose*/ ) {
-                mlt_log_warning(NULL, "shift: %5lf   %5lf   %lf \n", 
+                mlt_log_warning(NULL, "shift: %5lf   %5lf   %lf \n",
                            t.x, t.y, t.alpha *180/M_PI);
             }
-            ts[i] = add_transforms(&ts[i], &t); 
+            ts[i] = add_transforms(&ts[i], &t);
             t = ts[i];
         }
     }
@@ -534,13 +537,13 @@ int preprocess_transforms(TransformData* td)
         for (i = 0; i < td->trans_len; i++)
             ts[i].alpha = TC_CLAMP(ts[i].alpha, -td->maxangle, td->maxangle);
 
-    /* Calc optimal zoom 
+    /* Calc optimal zoom
      *  cheap algo is to only consider transformations
-     *  uses cleaned max and min 
+     *  uses cleaned max and min
      */
-    if (td->optzoom != 0 && td->trans_len > 1){    
+    if (td->optzoom != 0 && td->trans_len > 1){
         Transform min_t, max_t;
-        cleanmaxmin_xy_transform(ts, td->trans_len, 10, &min_t, &max_t); 
+        cleanmaxmin_xy_transform(ts, td->trans_len, 10, &min_t, &max_t);
         // the zoom value only for x
         double zx = 2*TC_MAX(max_t.x,fabs(min_t.x))/td->width_src;
         // the zoom value only for y
@@ -548,11 +551,11 @@ int preprocess_transforms(TransformData* td)
         td->zoom += 100* TC_MAX(zx,zy); // use maximum
         mlt_log_debug(NULL,"Final zoom: %lf\n", td->zoom);
     }
-        
+
     /* apply global zoom */
     if (td->zoom != 0){
         for (i = 0; i < td->trans_len; i++)
-            ts[i].zoom += td->zoom;       
+            ts[i].zoom += td->zoom;
     }
 
     return 1;
@@ -571,7 +574,7 @@ static int transform_init(TCModuleInstance *self, uint32_t features)
     TransformData* td = NULL;
     TC_MODULE_SELF_CHECK(self, "init");
     TC_MODULE_INIT_CHECK(self, MOD_FEATURES, features);
-    
+
     td = tc_zalloc(sizeof(TransformData));
     if (td == NULL) {
         tc_log_error(MOD_NAME, "init: out of memory!");
@@ -590,83 +593,83 @@ static int transform_init(TCModuleInstance *self, uint32_t features)
  * transform_configure:  Configure this instance of the module.  See
  * tcmodule-data.h for function details.
  */
-int transform_configure(TransformData *self,int width,int height, mlt_image_format  pixelformat, unsigned char* image ,Transform* tx,int trans_len) 
+int transform_configure(TransformData *self,int width,int height, mlt_image_format  pixelformat, unsigned char* image ,Transform* tx,int trans_len)
 {
     TransformData *td = self;
 
     /**** Initialise private data structure */
 
     /* td->framesize = td->vob->im_v_width *
-     *  MAX_PLANES * sizeof(char) * 2 * td->vob->im_v_height * 2;    
+     *  MAX_PLANES * sizeof(char) * 2 * td->vob->im_v_height * 2;
      */
        // rgb24 = w*h*3 , yuv420p = w* h* 3/2
-    td->framesize_src = width*height*(pixelformat==mlt_image_rgb24 ? 3 : (3.0/2.0));    
+    td->framesize_src = width*height*(pixelformat==mlt_image_rgb24 ? 3 : (3.0/2.0));
     td->src = malloc(td->framesize_src); /* FIXME */
     if (td->src == NULL) {
         mlt_log_error(NULL,"tc_malloc failed\n");
         return -1;
     }
-  
+
     td->width_src  = width;
     td->height_src = height;
-  
+
     /* Todo: in case we can scale the images, calc new size later */
     td->width_dest  = width;
     td->height_dest = height;
     td->framesize_dest = td->framesize_src;
     td->dest = 0;
-  
+
     td->trans = tx;
     td->trans_len = trans_len;
     td->current_trans = 0;
-    td->warned_transform_end = 0;  
+    td->warned_transform_end = 0;
 
     /* Options */
     // set from  filter td->maxshift = -1;
     // set from  filter td->maxangle = -1;
-    
+
 
     // set from  filter td->crop = 0;
     // set from  filter td->relative = 1;
     // set from  filter td->invert = 0;
     // set from  filter td->smoothing = 10;
-  
+
     td->rotation_threshhold = 0.25/(180/M_PI);
 
     // set from  filter td->zoom    = 0;
     // set from  filter td->optzoom = 1;
     // set from  filter td->interpoltype = 2; // bi-linear
     // set from  filter td->sharpen = 0.8;
-       
+
     td->interpoltype = TC_MIN(td->interpoltype,4);
     if (1) {
         mlt_log_debug(NULL, "Image Transformation/Stabilization Settings:\n");
         mlt_log_debug(NULL, "    smoothing = %d\n", td->smoothing);
         mlt_log_debug(NULL, "    maxshift  = %d\n", td->maxshift);
         mlt_log_debug(NULL, "    maxangle  = %f\n", td->maxangle);
-        mlt_log_debug(NULL, "    crop      = %s\n", 
+        mlt_log_debug(NULL, "    crop      = %s\n",
                         td->crop ? "Black" : "Keep");
-        mlt_log_debug(NULL, "    relative  = %s\n", 
+        mlt_log_debug(NULL, "    relative  = %s\n",
                     td->relative ? "True": "False");
-        mlt_log_debug(NULL, "    invert    = %s\n", 
+        mlt_log_debug(NULL, "    invert    = %s\n",
                     td->invert ? "True" : "False");
         mlt_log_debug(NULL, "    zoom      = %f\n", td->zoom);
-        mlt_log_debug(NULL, "    optzoom   = %s\n", 
+        mlt_log_debug(NULL, "    optzoom   = %s\n",
                     td->optzoom ? "On" : "Off");
-        mlt_log_debug(NULL, "    interpol  = %s\n", 
+        mlt_log_debug(NULL, "    interpol  = %s\n",
                     interpoltypes[td->interpoltype]);
         mlt_log_debug(NULL, "    sharpen   = %f\n", td->sharpen);
     }
-  
+
     if (td->maxshift > td->width_dest/2
         ) td->maxshift = td->width_dest/2;
     if (td->maxshift > td->height_dest/2)
         td->maxshift = td->height_dest/2;
-  
+
     if (!preprocess_transforms(td)) {
         mlt_log_error(NULL,"error while preprocessing transforms!");
-        return -1;            
-    }  
+        return -1;
+    }
 
     switch(td->interpoltype){
       case 0:  interpolate = &interpolateZero; break;
@@ -676,7 +679,7 @@ int transform_configure(TransformData *self,int width,int height, mlt_image_form
       case 4:  interpolate = &interpolateBiCub; break;
       default: interpolate = &interpolateBiLin;
     }
-    
+
     return 0;
 }
 
@@ -685,21 +688,21 @@ int transform_configure(TransformData *self,int width,int height, mlt_image_form
  * transform_filter_video: performs the transformation of frames
  * See tcmodule-data.h for function details.
  */
-int transform_filter_video(TransformData *self, 
-                                  unsigned char *frame,mlt_image_format pixelformat) 
+int transform_filter_video(TransformData *self,
+                                  unsigned char *frame,mlt_image_format pixelformat)
 {
     TransformData *td = self;
-  
+
 
     td->dest = frame;
     memcpy(td->src, frame, td->framesize_src);
-    if (td->current_trans >= td->trans_len) {        
+    if (td->current_trans >= td->trans_len) {
         td->current_trans = td->trans_len-1;
         if(!td->warned_transform_end)
             mlt_log_warning(NULL,"not enough transforms found, use last transformation!\n");
-        td->warned_transform_end = 1;        
+        td->warned_transform_end = 1;
     }
-  
+
     if (pixelformat == mlt_image_rgb24 ) {
         transformRGB(td);
     } else if (pixelformat == mlt_image_yuv420p) {
index 71fd9ea679c1fd3341cffc2cb3a53f69859d122e..3cd981ec5ba2e52fe4d9fad987b2d340acbf5e1b 100644 (file)
@@ -2,23 +2,23 @@
  *  filter_transform.c
  *
  *  Copyright (C) Georg Martius - June 2007
- *   georg dot martius at web dot de  
+ *   georg dot martius at web dot de
  *
  *  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. 
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * Typical call:
  * transcode -J transform -i inp.mpeg -y xdiv,tcaud inp_stab.avi
 #define DEFAULT_TRANS_FILE_NAME     "transforms.dat"
 
 #define PIXEL(img, x, y, w, h, def) ((x) < 0 || (y) < 0) ? def       \
-    : (((x) >=w || (y) >= h) ? def : img[(x) + (y) * w]) 
-#define PIX(img, x, y, w, h) (img[(x) + (y) * w]) 
+    : (((x) >=w || (y) >= h) ? def : img[(x) + (y) * w])
+#define PIX(img, x, y, w, h) (img[(x) + (y) * w])
+#define PIXN(img, x, y, w, h,N,channel) (img[((x) + (y) * w)*N+channel])
 // gives Pixel in N-channel image. channel in {0..N-1}
 #define PIXELN(img, x, y, w, h, N,channel , def) ((x) < 0 || (y) < 0) ? def  \
-    : (((x) >=w || (y) >= h) ? def : img[((x) + (y) * w)*N + channel]) 
+    : (((x) >=w || (y) >= h) ? def : img[((x) + (y) * w)*N + channel])
 
 typedef struct {
     int framesize_src;  // size of frame buffer in bytes (src)
@@ -53,23 +54,23 @@ typedef struct {
     int current_trans;   // index to current transformation
     int trans_len;       // length of trans array
     short warned_transform_end; // whether we warned that there is no transform left
+
     /* Options */
     int maxshift;        // maximum number of pixels we will shift
     double maxangle;     // maximum angle in rad
 
-    /* whether to consider transforms as relative (to previous frame) 
-     * or absolute transforms  
+    /* whether to consider transforms as relative (to previous frame)
+     * or absolute transforms
      */
-    int relative;  
-    /* number of frames (forward and backward) 
+    int relative;
+    /* number of frames (forward and backward)
      * to use for smoothing transforms */
-    int smoothing;  
+    int smoothing;
     int crop;       // 1: black bg, 0: keep border from last frame(s)
     int invert;     // 1: invert transforms, 0: nothing
     /* constants */
     /* threshhold below which no rotation is performed */
-    double rotation_threshhold; 
+    double rotation_threshhold;
     double zoom;      // percentage to zoom: 0->no zooming 10:zoom in 10%
     int optzoom;      // 1: determine optimal zoom, 0: nothing
     int interpoltype; // type of interpolation: 0->Zero,1->Lin,2->BiLin,3->Sqr
@@ -79,20 +80,20 @@ typedef struct {
 } TransformData;
 
 /* forward declarations, please look below for documentation*/
-void interpolateBiLinBorder(unsigned char *rv, float x, float y, 
-                            unsigned char* img, int w, int h, unsigned char def);
-void interpolateBiCub(unsigned char *rv, float x, float y, 
-                      unsigned char* img, int width, int height, unsigned char def);
-void interpolateSqr(unsigned char *rv, float x, float y, 
-                    unsigned char* img, int w, int h, unsigned char def);
-void interpolateBiLin(unsigned char *rv, float x, float y, 
-                      unsigned char* img, int w, int h, unsigned char def);
-void interpolateLin(unsigned char *rv, float x, float y, 
-                      unsigned char* img, int w, int h, unsigned char def);
-void interpolateZero(unsigned char *rv, float x, float y, 
-                     unsigned char* img, int w, int h, unsigned char def);
-void interpolateN(unsigned char *rv, float x, float y, 
-                  unsigned char* img, int width, int height, 
+void interpolateBiLinBorder(unsigned char *rv, float x, float y,
+                            unsigned char* img, int w, int h, unsigned char def,unsigned char N, unsigned char channel);
+void interpolateBiCub(unsigned char *rv, float x, float y,
+                      unsigned char* img, int width, int height, unsigned char def,unsigned char N, unsigned char channel);
+void interpolateSqr(unsigned char *rv, float x, float y,
+                    unsigned char* img, int w, int h, unsigned char def,unsigned char N, unsigned char channel);
+void interpolateBiLin(unsigned char *rv, float x, float y,
+                      unsigned char* img, int w, int h, unsigned char def,unsigned char N, unsigned char channel);
+void interpolateLin(unsigned char *rv, float x, float y,
+                      unsigned char* img, int w, int h, unsigned char def,unsigned char N, unsigned char channel);
+void interpolateZero(unsigned char *rv, float x, float y,
+                     unsigned char* img, int w, int h, unsigned char def,unsigned char N, unsigned char channel);
+void interpolateN(unsigned char *rv, float x, float y,
+                  unsigned char* img, int width, int height,
                   unsigned char N, unsigned char channel, unsigned char def);
 int transformRGB(TransformData* td);
 int transformYUV(TransformData* td);
@@ -100,25 +101,25 @@ int read_input_file(TransformData* td,tlist* list);
 int preprocess_transforms(TransformData* td);
 
 
-/** 
+/**
  * interpolate: general interpolation function pointer for one channel image data
  *
  * Parameters:
  *             rv: destination pixel (call by reference)
- *            x,y: the source coordinates in the image img. Note this 
+ *            x,y: the source coordinates in the image img. Note this
  *                 are real-value coordinates, that's why we interpolate
  *            img: source image
  *   width,height: dimension of image
  *            def: default value if coordinates are out of range
  * Return value:  None
  */
-/*void (*interpolate)(unsigned char *rv, float x, float y, 
-                    unsigned char* img, int width, int height, 
+/*void (*interpolate)(unsigned char *rv, float x, float y,
+                    unsigned char* img, int width, int height,
                     unsigned char def) = 0;
 */
 /** interpolateBiLinBorder: bi-linear interpolation function that also works at the border.
     This is used by many other interpolation methods at and outsize the border, see interpolate */
 int transform_configure(TransformData *self,int width,int height, mlt_image_format pixelformat, unsigned char* image,Transform* tx,int trans_len) ;
 
-int transform_filter_video(TransformData *self,       
+int transform_filter_video(TransformData *self,
                                                  unsigned char *frame,mlt_image_format pixelformat);