static void serialize_vectors( videostab self, mlt_position length ) { mlt_geometry g = mlt_geometry_init(); if ( g ) { struct mlt_geometry_item_s item; int i; // Initialize geometry item item.key = item.f[0] = item.f[1] = 1; item.f[2] = item.f[3] = item.f[4] = 0; for ( i = 0; i < length; i++ ) { // Set the geometry item item.frame = i; item.x = self->pos_h[i].x; item.y = self->pos_h[i].y; // Add the geometry item mlt_geometry_insert( g, &item ); } // Put the analysis results in a property mlt_geometry_set_length( g, length ); mlt_properties_set_data( MLT_FILTER_PROPERTIES( self->parent ), "vectors", g, 0, (mlt_destructor) mlt_geometry_close, (mlt_serialiser) mlt_geometry_serialise ); } }
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; }
// Parse the geometry specification for a given length and normalised width/height (-1 for default) // data is constructed as: [frame=]X/Y:WxH[:mix][!][;[frame=]X/Y:WxH[:mix][!]]* // and X, Y, W and H can have trailing % chars to indicate percentage of normalised size // Append a pair's value with ! to enable distort. int mlt_geometry_parse( mlt_geometry self, char *data, int length, int nw, int nh ) { int i = 0; // Create a tokeniser mlt_tokeniser tokens = mlt_tokeniser_init( ); // Get the local/private structure geometry g = self->local; // Clean the existing geometry mlt_geometry_clean( self ); // Update the info on the data if ( length != -1 ) g->length = length; if ( nw != -1 ) g->nw = nw; if ( nh != -1 ) g->nh = nh; if ( data != NULL ) g->data = strdup( data ); // Tokenise if ( data != NULL ) mlt_tokeniser_parse_new( tokens, data, ";" ); // Iterate through each token for ( i = 0; i < mlt_tokeniser_count( tokens ); i ++ ) { struct mlt_geometry_item_s item; char *value = mlt_tokeniser_get_string( tokens, i ); // If no data in keyframe, drop it (trailing semicolon) if ( value == NULL || !strcmp( value, "" ) ) continue; // Set item to 0 memset( &item, 0, sizeof( struct mlt_geometry_item_s ) ); // Now parse the item mlt_geometry_parse_item( self, &item, value ); // Now insert into place mlt_geometry_insert( self, &item ); } mlt_geometry_interpolate( self ); // Remove the tokeniser mlt_tokeniser_close( tokens ); // ??? return 0; }
mlt_producer producer_pango_init( const char *filename ) { producer_pango this = calloc( sizeof( struct producer_pango_s ), 1 ); if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 ) { mlt_producer producer = &this->parent; pthread_mutex_lock( &pango_mutex ); if ( fontmap == NULL ) fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new(); g_type_init(); pthread_mutex_unlock( &pango_mutex ); producer->get_frame = producer_get_frame; producer->close = ( mlt_destructor )producer_close; // Get the properties interface mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent ); // Set the default properties mlt_properties_set( properties, "fgcolour", "0xffffffff" ); mlt_properties_set( properties, "bgcolour", "0x00000000" ); mlt_properties_set( properties, "olcolour", "0x00000000" ); mlt_properties_set_int( properties, "align", pango_align_left ); mlt_properties_set_int( properties, "pad", 0 ); mlt_properties_set_int( properties, "outline", 0 ); mlt_properties_set( properties, "text", "" ); mlt_properties_set( properties, "font", NULL ); mlt_properties_set( properties, "family", "Sans" ); mlt_properties_set_int( properties, "size", 48 ); mlt_properties_set( properties, "style", "normal" ); mlt_properties_set( properties, "encoding", "UTF-8" ); mlt_properties_set_int( properties, "weight", PANGO_WEIGHT_NORMAL ); mlt_properties_set_int( properties, "seekable", 1 ); if ( filename == NULL || ( filename && ( !strcmp( filename, "" ) // workaround for old kdenlive countdown generator || strstr( filename, "<producer>" ) ) ) ) { mlt_properties_set( properties, "markup", "" ); } else if ( filename[ 0 ] == '+' || strstr( filename, "/+" ) ) { char *copy = strdup( filename + 1 ); char *markup = copy; if ( strstr( markup, "/+" ) ) markup = strstr( markup, "/+" ) + 2; ( *strrchr( markup, '.' ) ) = '\0'; while ( strchr( markup, '~' ) ) ( *strchr( markup, '~' ) ) = '\n'; mlt_properties_set( properties, "resource", filename ); mlt_properties_set( properties, "markup", markup ); free( copy ); } else if ( strstr( filename, ".mpl" ) ) { int i = 0; mlt_properties contents = mlt_properties_load( filename ); mlt_geometry key_frames = mlt_geometry_init( ); struct mlt_geometry_item_s item; mlt_properties_set( properties, "resource", filename ); mlt_properties_set_data( properties, "contents", contents, 0, ( mlt_destructor )mlt_properties_close, NULL ); mlt_properties_set_data( properties, "key_frames", key_frames, 0, ( mlt_destructor )mlt_geometry_close, NULL ); // Make sure we have at least one entry if ( mlt_properties_get( contents, "0" ) == NULL ) mlt_properties_set( contents, "0", "" ); for ( i = 0; i < mlt_properties_count( contents ); i ++ ) { char *name = mlt_properties_get_name( contents, i ); char *value = mlt_properties_get_value( contents, i ); while ( value != NULL && strchr( value, '~' ) ) ( *strchr( value, '~' ) ) = '\n'; item.frame = atoi( name ); mlt_geometry_insert( key_frames, &item ); } mlt_geometry_interpolate( key_frames ); } else { FILE *f = fopen( filename, "r" ); if ( f != NULL ) { char line[81]; char *markup = NULL; size_t size = 0; line[80] = '\0'; while ( fgets( line, 80, f ) ) { size += strlen( line ) + 1; if ( markup ) { markup = realloc( markup, size ); strcat( markup, line ); } else { markup = strdup( line ); } } fclose( f ); if ( markup[ strlen( markup ) - 1 ] == '\n' ) markup[ strlen( markup ) - 1 ] = '\0'; mlt_properties_set( properties, "resource", filename ); mlt_properties_set( properties, "markup", ( markup == NULL ? "" : markup ) ); free( markup ); } else { producer->close = NULL; mlt_producer_close( producer ); producer = NULL; free( this ); } } return producer; } free( this ); return NULL; }
// 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; }