예제 #1
0
static void deserialize_vectors( videostab self, char *vectors, mlt_position length )
{
	mlt_geometry g = mlt_geometry_init();

	// Parse the property as a geometry
	if ( g && !mlt_geometry_parse( g, vectors, length, -1, -1 ) )
	{
		struct mlt_geometry_item_s item;
		int i;

		// Copy the geometry items to a vc array for interp()
		for ( i = 0; i < length; i++ )
		{
			mlt_geometry_fetch( g, &item, i );
			self->pos_h[i].x = item.x;
			self->pos_h[i].y = item.y;
		}
	}
	else
	{
		mlt_log_warning( MLT_FILTER_SERVICE(self->parent), "failed to parse vectors\n" );
	}

	// We are done with this mlt_geometry
	if ( g ) mlt_geometry_close( g );
}
예제 #2
0
static int attach_boundry_to_frame( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
	// Get the filter object
	mlt_filter filter = mlt_frame_pop_service( frame );

	// Get the filter's property object
	mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);

	// Get the frame properties
	mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame);

	// Get the frame position
	mlt_position position = mlt_filter_get_position( filter, frame );
	
	mlt_service_lock( MLT_FILTER_SERVICE( filter ) );

	// 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;

		mlt_geometry_insert( geom, &item );
		mlt_geometry_interpolate( geom );
		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);
	}

	mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );

	// 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);

	// Cleanse the geometry item
	geometry_item->w = geometry_item->x < 0 ? geometry_item->w + geometry_item->x : geometry_item->w;
	geometry_item->h = geometry_item->y < 0 ? geometry_item->h + geometry_item->y : geometry_item->h;
	geometry_item->x = geometry_item->x < 0 ? 0 : geometry_item->x;
	geometry_item->y = geometry_item->y < 0 ? 0 : geometry_item->y;
	geometry_item->w = geometry_item->w < 0 ? 0 : geometry_item->w;
	geometry_item->h = geometry_item->h < 0 ? 0 : geometry_item->h;

	mlt_properties_set_data( frame_properties, "bounds", geometry_item, sizeof( struct mlt_geometry_item_s ), mlt_pool_release, NULL );

	// Get the new image
	int error = mlt_frame_get_image( frame, image, format, width, height, 1 );

	if( error != 0 )
		mlt_properties_debug( frame_properties, "error after mlt_frame_get_image() in autotrack_rectangle attach_boundry_to_frame", stderr );

	return error;
}
예제 #3
0
static void geometry_calculate( mlt_transition transition, const char *store, struct mlt_geometry_item_s *output, double position )
{
	mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
	mlt_geometry geometry = mlt_properties_get_data( properties, store, NULL );
	int mirror_off = mlt_properties_get_int( properties, "mirror_off" );
	int repeat_off = mlt_properties_get_int( properties, "repeat_off" );
	int length = mlt_geometry_get_length( geometry );

	// Allow wrapping
	if ( !repeat_off && position >= length && length != 0 )
	{
		int section = position / length;
		position -= section * length;
		if ( !mirror_off && section % 2 == 1 )
			position = length - position;
	}

	// Fetch the key for the position
	mlt_geometry_fetch( geometry, output, position );
}
예제 #4
0
파일: mlt_geometry.c 프로젝트: Enlik/mlt
char *mlt_geometry_serialise_cut( mlt_geometry self, int in, int out )
{
	geometry g = self->local;
	struct mlt_geometry_item_s item;
	char *ret = malloc( 1000 );
	int used = 0;
	int size = 1000;

	if ( in == -1 )
		in = 0;
	if ( out == -1 )
		out = mlt_geometry_get_length( self );

	if ( ret != NULL )
	{
		char temp[ 100 ];

		strcpy( ret, "" );

		item.frame = in;

		while( 1 )
		{
			strcpy( temp, "" );

			// If it's the first frame, then it's not necessarily a key
			if ( item.frame == in )
			{
				if ( mlt_geometry_fetch( self, &item, item.frame ) )
					break;

				// If the first key is larger than the current position
				// then do nothing here
				if ( g->item->data.frame > item.frame )
				{
					item.frame ++;
					continue;
				}

				// To ensure correct seeding, ensure all values are fixed
				item.f[0] = 1;
				item.f[1] = 1;
				item.f[2] = 1;
				item.f[3] = 1;
				item.f[4] = 1;
			}
			// Typically, we move from key to key
			else if ( item.frame < out )
			{
				if ( mlt_geometry_next_key( self, &item, item.frame ) )
					break;

				// Special case - crop at the out point
				if ( item.frame > out )
					mlt_geometry_fetch( self, &item, out );
			}
			// We've handled the last key
			else
			{
				break;
			}

			if ( item.frame - in != 0 )
				sprintf( temp, "%d=", item.frame - in );

			if ( item.f[0] )
				sprintf( temp + strlen( temp ), "%g", item.x );
			if ( item.f[1] ) {
				strcat( temp, "/" );
				sprintf( temp + strlen( temp ), "%g", item.y );
			}
			if ( item.f[2] ) {
				strcat( temp, ":" );
				sprintf( temp + strlen( temp ), "%g", item.w );
			}
			if ( item.f[3] ) {
				strcat( temp, "x" );
				sprintf( temp + strlen( temp ), "%g", item.h );
			}
			if ( item.f[4] ) {
				strcat( temp, ":" );
				sprintf( temp + strlen( temp ), "%g", item.mix );
			}

			if ( used + strlen( temp ) + 2 > size ) // +2 for ';' and NULL
			{
				size += 1000;
				ret = realloc( ret, size );
			}

			if ( ret != NULL && used != 0 )
			{
				used ++;
				strcat( ret, ";" );
			}
			if ( ret != NULL )
			{
				used += strlen( temp );
				strcat( ret, temp );
			}

			item.frame ++;
		}
	}

	return ret;
}
예제 #5
0
파일: mlt_geometry.c 프로젝트: Enlik/mlt
int mlt_geometry_parse_item( mlt_geometry self, mlt_geometry_item item, char *value )
{
	int ret = 0;

	// Get the local/private structure
	geometry g = self->local;

	if ( value != NULL && strcmp( value, "" ) )
	{
		char *p = strchr( value, '=' );
		int count = 0;
		double temp;

		// Determine if a position has been specified
		if ( p != NULL )
		{
			temp = atof( value );
			if ( temp > -1 && temp < 1 )
				item->frame = temp * g->length;
			else
				item->frame = temp;
			value = p + 1;
		}

		// Special case - frame < 0
		if ( item->frame < 0 )
			item->frame += g->length;

		// Obtain the current value at this position - self allows new
		// frames to be created which don't specify all values
		mlt_geometry_fetch( self, item, item->frame );

		// Special case - when an empty string is specified, all values are fixed
		// TODO: Check if this is logical - it's convenient, but it's also odd...
		if ( !*value )
		{
			item->f[0] = 1;
			item->f[1] = 1;
			item->f[2] = 1;
			item->f[3] = 1;
			item->f[4] = 1;
		}

		// Iterate through the remainder of value
		while( *value )
		{
			// Get the value
			temp = strtod( value, &p );

			// Check if a value was specified
			if ( p != value )
			{
				// Handle the % case
				if ( *p == '%' )
				{
					if ( count == 0 || count == 2 )
						temp *= g->nw / 100.0;
					else if ( count == 1 || count == 3 )
						temp *= g->nh / 100.0;
					p ++;
				}

				// Special case - distort token
				if ( *p == '!' || *p == '*' )
				{
					p ++;
					item->distort = 1;
				}

				// Actually, we don't care about the delimiter at all..
				if ( *p ) p ++;

				// Assign to the item
				switch( count )
				{
					case 0: item->x = temp; item->f[0] = 1; break;
					case 1: item->y = temp; item->f[1] = 1; break;
					case 2: item->w = temp; item->f[2] = 1; break;
					case 3: item->h = temp; item->f[3] = 1; break;
					case 4: item->mix = temp; item->f[4] = 1; break;
				}
			}
			else
			{
				p ++;
			}

			// Update the value pointer
			value = p;
			count ++;
		}
	}
	else
	{
		ret = 1;
	}

	return ret;
}
예제 #6
0
// Image stack(able) method
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{

	// Get the filter object
	mlt_filter filter = mlt_frame_pop_service( frame );

	// Get the filter's property object
	mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);

	// Get the frame properties
	mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame);

	// Get the frame position
	mlt_position position = mlt_filter_get_position( filter, frame );

	// Get the new image
	int error = mlt_frame_get_image( frame, image, format, width, height, 1 );

	if( error != 0 )
		mlt_properties_debug( frame_properties, "error after mlt_frame_get_image() in autotrack_rectangle", stderr );

	mlt_service_lock( MLT_FILTER_SERVICE( filter ) );

	// Get the geometry object
	mlt_geometry geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL);

	// Get the current geometry item
	struct mlt_geometry_item_s boundry;
	mlt_geometry_fetch(geometry, &boundry, position);

	// Get the motion vectors
	struct motion_vector_s *vectors = mlt_properties_get_data( frame_properties, "motion_est.vectors", NULL );

	// Cleanse the geometry item
	boundry.w = boundry.x < 0 ? boundry.w + boundry.x : boundry.w;
	boundry.h = boundry.y < 0 ? boundry.h + boundry.y : boundry.h;
	boundry.x = boundry.x < 0 ? 0 : boundry.x;
	boundry.y = boundry.y < 0 ? 0 : boundry.y;
	boundry.w = boundry.w < 0 ? 0 : boundry.w;
	boundry.h = boundry.h < 0 ? 0 : boundry.h;

	// How did the rectangle move?
	if( vectors != NULL &&
	    boundry.key != 1 ) // Paused?
	{

		int method = mlt_properties_get_int( filter_properties, "method" );

		// Get the size of macroblocks in pixel units
		int macroblock_height = mlt_properties_get_int( frame_properties, "motion_est.macroblock_height" );
		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, *width, *height );


		// 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);
		mlt_geometry_interpolate(geometry);
	}

	mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );

	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, "_serialize" ) == 1 )
	{
		// Add the vector change to the list
		mlt_geometry key_frames = mlt_properties_get_data( filter_properties, "motion_vector_list", NULL );
		if ( !key_frames )
		{
			key_frames = mlt_geometry_init();
			mlt_properties_set_data( filter_properties, "motion_vector_list", key_frames, 0,
			                         (mlt_destructor) mlt_geometry_close, (mlt_serialiser) mlt_geometry_serialise );
			if ( key_frames )
				mlt_geometry_set_length( key_frames, mlt_filter_get_length2( filter, frame ) );
		}
		if ( key_frames )
		{
			struct mlt_geometry_item_s item;
			item.frame = (int) mlt_frame_get_position( frame );
			item.key = 1;
			item.x = boundry.x;
			item.y = boundry.y;
			item.w = boundry.w;
			item.h = boundry.h;
			item.mix = 0;
			item.f[0] = item.f[1] = item.f[2] = item.f[3] = 1;
			item.f[4] = 0;
			mlt_geometry_insert( key_frames, &item );
		}
	}
	
	if( mlt_properties_get_int( filter_properties, "obscure" ) == 1 )
	{
		mlt_filter obscure = mlt_properties_get_data( filter_properties, "_obscure", NULL );

		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 )
	{
		fprintf( stderr, "%d,%d,%d,%d\n", (int)boundry.x, (int)boundry.y, (int)boundry.w, (int)boundry.h );
		fflush( stdout );
	}

	return error;
}