X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Fmotion_est%2Ffilter_autotrack_rectangle.c;h=0d526e4547bb3a266a2502edfaa40ba1fac80fa4;hb=bcbe5ecf7001335895da8be92518f4645977a839;hp=5553ee8c4181b969f29ecffd9ae94651f6756954;hpb=d42d151587fbaeb9843a76020395a55ebb33e0e1;p=melted diff --git a/src/modules/motion_est/filter_autotrack_rectangle.c b/src/modules/motion_est/filter_autotrack_rectangle.c index 5553ee8..0d526e4 100644 --- a/src/modules/motion_est/filter_autotrack_rectangle.c +++ b/src/modules/motion_est/filter_autotrack_rectangle.c @@ -35,38 +35,23 @@ #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; -} - void caculate_motion( struct motion_vector_s *vectors, mlt_geometry_item boundry, int macroblock_width, int macroblock_height, int mv_buffer_width, - int method ) + int method, + int width, + int height ) { // 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; @@ -75,10 +60,9 @@ 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; } @@ -94,8 +78,8 @@ void caculate_motion( struct motion_vector_s *vectors, 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; @@ -106,8 +90,20 @@ void caculate_motion( struct motion_vector_s *vectors, if ( n == 0 ) return; - boundry->x -= average2_x / n; - boundry->y -= average2_y / n; + boundry->x -= (double)average2_x / (double)n; + boundry->y -= (double)average2_y / (double)n; + + if ( boundry->x < 0 ) + boundry->x = 0; + + if ( boundry->y < 0 ) + boundry->y = 0; + + if ( boundry->x + boundry->w > width ) + boundry->x = width - boundry->w; + + if ( boundry->y + boundry->h > height ) + boundry->y = height - boundry->h; } // Image stack(able) method @@ -133,7 +129,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format mlt_properties_debug( frame_properties, "error after mlt_frame_get_image() in autotrack_rectangle", stderr ); // Get the geometry object - mlt_geometry geometry = mlt_properties_get_data(filter_properties, "geometry", NULL); + mlt_geometry geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL); // Get the current geometry item struct mlt_geometry_item_s boundry; @@ -141,9 +137,11 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format // 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" ); @@ -152,29 +150,44 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format int macroblock_width = mlt_properties_get_int( frame_properties, "motion_est.macroblock_width" ); int mv_buffer_width = *width / macroblock_width; - caculate_motion( vectors, &boundry, macroblock_width, macroblock_height, mv_buffer_width, method ); + caculate_motion( vectors, &boundry, macroblock_width, macroblock_height, mv_buffer_width, method, *width, *height ); - } - // Turn the geometry object into 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); + // 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 ) + { + init_arrows( format, *width, *height ); + draw_rectangle_outline(*image, boundry.x, boundry.y, boundry.w, boundry.h, 100); + } - if( mlt_properties_get_int( filter_properties, "debug" ) == 1 ) + if( mlt_properties_get_int( filter_properties, "obscure" ) == 1 ) { + mlt_filter obscure = mlt_properties_get_data( filter_properties, "_obscure", NULL ); - init_arrows( format, *width, *height ); - draw_line(*image, boundry.x, boundry.y, boundry.x, boundry.y + boundry.h, 100); - draw_line(*image, boundry.x, boundry.y + boundry.h, boundry.x + boundry.w, boundry.y + boundry.h, 100); - draw_line(*image, boundry.x + boundry.w, boundry.y + boundry.h, boundry.x + boundry.w, boundry.y, 100); - draw_line(*image, boundry.x + boundry.w, boundry.y, boundry.x, boundry.y, 100); + mlt_properties_pass_list( MLT_FILTER_PROPERTIES(obscure), filter_properties, "in, out"); + + // Because filter_obscure needs to be rewritten to use mlt_geometry + char geom[100]; + sprintf( geom, "%d,%d:%dx%d", (int)boundry.x, (int)boundry.y, (int)boundry.w, (int)boundry.h ); + mlt_properties_set( MLT_FILTER_PROPERTIES( obscure ), "start", geom ); + mlt_properties_set( MLT_FILTER_PROPERTIES( obscure ), "end", geom ); + } + + if( mlt_properties_get_int( filter_properties, "collect" ) == 1 ) + { + printf( "%d,%d,%d,%d\n", (int)boundry.x, (int)boundry.y, (int)boundry.w, (int)boundry.h ); + fflush( stdout ); } + return error; } @@ -191,14 +204,29 @@ 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 + mlt_geometry geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL); + if (geometry == NULL) { + mlt_geometry geom = mlt_geometry_init(); + char *arg = mlt_properties_get(filter_properties, "geometry"); + + // Initialize with the supplied geometry + struct mlt_geometry_item_s item; + mlt_geometry_parse_item( geom, &item, arg ); + + item.frame = 0; + item.key = 1; + item.mix = 100; - // gEt the geometry object - mlt_geometry geometry = mlt_properties_get_data(filter_properties, "geometry", NULL); + mlt_geometry_insert( geom, &item ); + mlt_properties_set_data( filter_properties, "filter_geometry", geom, 0, (mlt_destructor)mlt_geometry_close, (mlt_serialiser)mlt_geometry_serialise ); + geometry = mlt_properties_get_data(filter_properties, "filter_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 ); @@ -238,14 +266,28 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(this), "debug" ) == 1 ) { mlt_filter vismv = mlt_properties_get_data( MLT_FILTER_PROPERTIES(this), "_vismv", NULL ); - if( vismv == NULL ) { - vismv = mlt_factory_filter( "vismv", NULL ); + if( vismv == NULL ) + { + mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) ); + vismv = mlt_factory_filter( profile, "vismv", NULL ); mlt_properties_set_data( MLT_FILTER_PROPERTIES(this), "_vismv", vismv, 0, (mlt_destructor)mlt_filter_close, NULL ); } mlt_filter_process( vismv, frame ); } + if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(this), "obscure" ) == 1 ) + { + mlt_filter obscure = mlt_properties_get_data( MLT_FILTER_PROPERTIES(this), "_obscure", NULL ); + if( obscure == NULL ) + { + mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) ); + obscure = mlt_factory_filter( profile, "obscure", NULL ); + mlt_properties_set_data( MLT_FILTER_PROPERTIES(this), "_obscure", obscure, 0, (mlt_destructor)mlt_filter_close, NULL ); + } + + mlt_filter_process( obscure, frame ); + } return frame; } @@ -254,36 +296,21 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) */ -mlt_filter filter_autotrack_rectangle_init( char *arg ) +mlt_filter filter_autotrack_rectangle_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { mlt_filter this = mlt_filter_new( ); if ( this != NULL ) { this->process = filter_process; + // Initialize with the supplied geometry if ther is one + if( arg != NULL ) + mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "geometry", arg ); + else + mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "geometry", "100,100:100x100" ); - mlt_geometry geometry = mlt_geometry_init(); - - // Initialize with the supplied geometry - if( arg != NULL ) { - - struct mlt_geometry_item_s item; - - mlt_geometry_parse_item( geometry, &item, arg ); - - item.frame = 0; - item.key = 1; - item.mix = 100; - - mlt_geometry_insert( geometry, &item ); - - } - - // ... 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); + // create an instance of the motion_est and obscure filter + mlt_filter motion_est = mlt_factory_filter( profile, "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 ); else {