X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Fmotion_est%2Ffilter_autotrack_rectangle.c;h=87d36dd28d2ea3125059ccac9272b38dc1b72017;hb=f4bb8619271de912e431dbaf5a4a7eb197b9ed04;hp=90efadbb97fcf0c06f6f9112fff7735d1cf85d6d;hpb=4f3d5f48dd9b4a0caddce6b65d9f8d4ad7a4f04a;p=melted diff --git a/src/modules/motion_est/filter_autotrack_rectangle.c b/src/modules/motion_est/filter_autotrack_rectangle.c index 90efadb..87d36dd 100644 --- a/src/modules/motion_est/filter_autotrack_rectangle.c +++ b/src/modules/motion_est/filter_autotrack_rectangle.c @@ -21,6 +21,7 @@ */ #include "filter_motion_est.h" +#include "arrow_code.h" #include @@ -34,100 +35,6 @@ #define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) #define ABS(a) ((a) >= 0 ? (a) : (-(a))) -// ffmpeg borrowed -static inline int clip(int a, int amin, int amax) -{ - if (a < amin) - return amin; - else if (a > amax) - return amax; - else - return a; -} - - -/** - * draws an line from (ex, ey) -> (sx, sy). - * Credits: modified from ffmpeg project - * @param ystride stride/linesize of the image - * @param xstride stride/element size of the image - * @param color color of the arrow - */ -static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h, int xstride, int ystride, int color){ - int t, x, y, fr, f; - -// buf[sy*ystride + sx*xstride]= color; - buf[sy*ystride + sx]+= color; - - sx= clip(sx, 0, w-1); - sy= clip(sy, 0, h-1); - ex= clip(ex, 0, w-1); - ey= clip(ey, 0, h-1); - - if(ABS(ex - sx) > ABS(ey - sy)){ - if(sx > ex){ - t=sx; sx=ex; ex=t; - t=sy; sy=ey; ey=t; - } - buf+= sx*xstride + sy*ystride; - ex-= sx; - f= ((ey-sy)<<16)/ex; - for(x= 0; x <= ex; x++){ - y = (x*f)>>16; - fr= (x*f)&0xFFFF; - buf[ y *ystride + x*xstride]= (color*(0x10000-fr))>>16; - buf[(y+1)*ystride + x*xstride]= (color* fr )>>16; - } - }else{ - if(sy > ey){ - t=sx; sx=ex; ex=t; - t=sy; sy=ey; ey=t; - } - buf+= sx*xstride + sy*ystride; - ey-= sy; - if(ey) f= ((ex-sx)<<16)/ey; - else f= 0; - for(y= 0; y <= ey; y++){ - x = (y*f)>>16; - fr= (y*f)&0xFFFF; - buf[y*ystride + x *xstride]= (color*(0x10000-fr))>>16;; - buf[y*ystride + (x+1)*xstride]= (color* fr )>>16;; - } - } -} - -/** - * draws an arrow from (ex, ey) -> (sx, sy). - * Credits: modified from ffmpeg project - * @param stride stride/linesize of the image - * @param color color of the arrow - */ -static __attribute__((used)) void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h, int xstride, int ystride, int color){ - int dx,dy; - -// sx= clip(sx, -100, w+100); -// sy= clip(sy, -100, h+100); -// ex= clip(ex, -100, w+100); -// ey= clip(ey, -100, h+100); - - dx= ex - sx; - dy= ey - sy; - - if(dx*dx + dy*dy > 3*3){ - int rx= dx + dy; - int ry= -dx + dy; - int length= sqrt((rx*rx + ry*ry)<<8); - - //FIXME subpixel accuracy - rx= ROUNDED_DIV(rx*3<<4, length); - ry= ROUNDED_DIV(ry*3<<4, length); - - draw_line(buf, sx, sy, sx + rx, sy + ry, w, h, xstride, ystride, color); - draw_line(buf, sx, sy, sx - ry, sy + rx, w, h, xstride, ystride, color); - } - draw_line(buf, sx, sy, ex, ey, w, h, xstride, ystride, color); -} - void caculate_motion( struct motion_vector_s *vectors, mlt_geometry_item boundry, int macroblock_width, @@ -139,16 +46,10 @@ void caculate_motion( struct motion_vector_s *vectors, // translate pixel units (from bounds) to macroblock units // make sure whole macroblock stay within bounds - // I know; it hurts. - int left_mb = boundry->x / macroblock_width; - left_mb += ( (int)boundry->x % macroblock_width == 0 ) ? 0 : 1 ; - int top_mb = boundry->y / macroblock_height; - top_mb += ( (int)boundry->y % macroblock_height == 0 ) ? 0 : 1 ; - - int right_mb = (boundry->x + boundry->w + 1) / macroblock_width; - right_mb -= ( (int)(boundry->x + boundry->w + 1) % macroblock_width == 0 ) ? 0 : 1 ; - int bottom_mb = (boundry->y + boundry->h + 1) / macroblock_height; - bottom_mb -= ( (int)(boundry->y + boundry->h + 1) % macroblock_height == 0 ) ? 0 : 1 ; + int left_mb = ( boundry->x + macroblock_width - 1 ) / macroblock_width; + int top_mb = ( boundry->y + macroblock_height - 1 ) / macroblock_height; + int right_mb = ( boundry->x + boundry->w ) / macroblock_width - 1; + int bottom_mb = ( boundry->y + boundry->h ) / macroblock_height - 1; int i, j, n = 0; @@ -157,38 +58,38 @@ void caculate_motion( struct motion_vector_s *vectors, #define CURRENT ( vectors + j*mv_buffer_width + i ) for( i = left_mb; i <= right_mb; i++ ){ - for( j = top_mb; j <= bottom_mb; j++ ){ - + for( j = top_mb; j <= bottom_mb; j++ ) + { n++; - average_x += CURRENT->dx; average_y += CURRENT->dy; } } - if ( n == 0 ) - return; + if ( n == 0 ) return; average_x /= n; average_y /= n; + n = 0; int average2_x = 0, average2_y = 0; for( i = left_mb; i <= right_mb; i++ ){ for( j = top_mb; j <= bottom_mb; j++ ){ - if( ABS(CURRENT->dx - average_x) < 5 && - ABS(CURRENT->dy - average_y) < 5 ) + if( ABS(CURRENT->dx - average_x) < 3 && + ABS(CURRENT->dy - average_y) < 3 ) { + n++; average2_x += CURRENT->dx; average2_y += CURRENT->dy; } } } - - boundry->x -= average2_x/n; - boundry->y -= average2_y/n; + if ( n == 0 ) return; + boundry->x -= (double)average2_x / (double)n; + boundry->y -= (double)average2_y / (double)n; } // Image stack(able) method @@ -219,13 +120,14 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format // Get the current geometry item struct mlt_geometry_item_s boundry; mlt_geometry_fetch(geometry, &boundry, position); -//fprintf(stderr, "process %d\n", position); // Get the motion vectors struct motion_vector_s *vectors = mlt_properties_get_data( frame_properties, "motion_est.vectors", NULL ); - + // How did the rectangle move? - if( vectors != NULL ) { + if( vectors != NULL && + boundry.key != 1 ) // Paused? + { int method = mlt_properties_get_int( filter_properties, "method" ); @@ -236,43 +138,23 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format caculate_motion( vectors, &boundry, macroblock_width, macroblock_height, mv_buffer_width, method ); - } - - boundry.key = 1; - - boundry.f[0] = 1; - boundry.f[1] = 1; - boundry.f[2] = 1; - boundry.f[3] = 1; - boundry.f[4] = 1; - -// boundry.frame = position; - - mlt_geometry_insert(geometry, &boundry); + // Make the geometry object a real boy + boundry.key = 1; + boundry.f[0] = 1; + boundry.f[1] = 1; + boundry.f[2] = 1; + boundry.f[3] = 1; + boundry.f[4] = 1; + mlt_geometry_insert(geometry, &boundry); + } - if( mlt_properties_get_int( filter_properties, "debug" ) == 1 ) + if( mlt_properties_get_int( filter_properties, "debug" ) == 1 ) { - int xstep, ystep; - - // Calculate the size of our steps (the number of bytes that seperate adjacent pixels in X and Y direction) - switch( *format ) { - case mlt_image_yuv422: - xstep = 2; - ystep = xstep * *width; - break; - default: - // I don't know - return -1; - break; - } + init_arrows( format, *width, *height ); + draw_rectangle_outline(*image, boundry.x, boundry.y, boundry.w, boundry.h, 100); + } - draw_line(*image, boundry.x, boundry.y, boundry.x, boundry.y + boundry.h, *width, *height, xstep, ystep, 0xff); - draw_line(*image, boundry.x, boundry.y + boundry.h, boundry.x + boundry.w, boundry.y + boundry.h, *width, *height, xstep, ystep, 0xff); - draw_line(*image, boundry.x + boundry.w, boundry.y + boundry.h, boundry.x + boundry.w, boundry.y, *width, *height, xstep, ystep, 0xff); - draw_line(*image, boundry.x + boundry.w, boundry.y, boundry.x, boundry.y, *width, *height, xstep, ystep, 0xff); - - } return error; } @@ -290,13 +172,12 @@ static int attach_boundry_to_frame( mlt_frame frame, uint8_t **image, mlt_image_ // Get the frame position mlt_position position = mlt_frame_get_position( frame ); - // gEt the geometry object + // Get the geometry object mlt_geometry geometry = mlt_properties_get_data(filter_properties, "geometry", NULL); // Get the current geometry item mlt_geometry_item geometry_item = mlt_pool_alloc( sizeof( struct mlt_geometry_item_s ) ); mlt_geometry_fetch(geometry, geometry_item, position); -//fprintf(stderr, "attach %d\n", position); mlt_properties_set_data( frame_properties, "bounds", geometry_item, sizeof( struct mlt_geometry_item_s ), mlt_pool_release, NULL ); @@ -315,9 +196,6 @@ static int attach_boundry_to_frame( mlt_frame frame, uint8_t **image, mlt_image_ static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) { - //mlt_properties_debug(MLT_SERVICE_PROPERTIES(mlt_service_consumer(mlt_filter_service(this))), "consumer!", stderr); - - /* modify the frame with the current geometry */ mlt_frame_push_service( frame, this); mlt_frame_push_get_image( frame, attach_boundry_to_frame ); @@ -380,8 +258,10 @@ mlt_filter filter_autotrack_rectangle_init( char *arg ) } + // ... and attach it to the frame mlt_properties_set_data( MLT_FILTER_PROPERTIES(this), "geometry", geometry, 0, (mlt_destructor)mlt_geometry_close, (mlt_serialiser)mlt_geometry_serialise ); + // create an instance of the motion_est filter mlt_filter motion_est = mlt_factory_filter("motion_est", NULL); if( motion_est != NULL ) mlt_properties_set_data( MLT_FILTER_PROPERTIES(this), "_motion_est", motion_est, 0, (mlt_destructor)mlt_filter_close, NULL ); @@ -390,8 +270,7 @@ mlt_filter filter_autotrack_rectangle_init( char *arg ) return NULL; } - //mlt_events_init( this ); - //mlt_events_listen(mlt_service_consumer(mlt_filter_service(this) + } return this;