static void attach_normalisers( mlt_profile profile, mlt_producer producer ) { // Loop variable int i; // Tokeniser mlt_tokeniser tokeniser = mlt_tokeniser_init( ); // We only need to load the normalising properties once if ( normalisers == NULL ) { char temp[ 1024 ]; sprintf( temp, "%s/core/loader.ini", mlt_environment( "MLT_DATA" ) ); normalisers = mlt_properties_load( temp ); mlt_factory_register_for_clean_up( normalisers, ( mlt_destructor )mlt_properties_close ); } // Apply normalisers for ( i = 0; i < mlt_properties_count( normalisers ); i ++ ) { int j = 0; int created = 0; char *value = mlt_properties_get_value( normalisers, i ); mlt_tokeniser_parse_new( tokeniser, value, "," ); for ( j = 0; !created && j < mlt_tokeniser_count( tokeniser ); j ++ ) create_filter( profile, producer, mlt_tokeniser_get_string( tokeniser, j ), &created ); } // Close the tokeniser mlt_tokeniser_close( tokeniser ); }
static void query_services( mlt_repository repo, mlt_service_type type ) { mlt_properties services = NULL; const char *typestr = NULL; switch ( type ) { case consumer_type: services = mlt_repository_consumers( repo ); typestr = "consumers"; break; case filter_type: services = mlt_repository_filters( repo ); typestr = "filters"; break; case producer_type: services = mlt_repository_producers( repo ); typestr = "producers"; break; case transition_type: services = mlt_repository_transitions( repo ); typestr = "transitions"; break; default: return; } fprintf( stderr, "---\n%s:\n", typestr ); if ( services ) { int j; for ( j = 0; j < mlt_properties_count( services ); j++ ) fprintf( stderr, " - %s\n", mlt_properties_get_name( services, j ) ); } fprintf( stderr, "...\n" ); }
static mlt_filter obtain_filter( mlt_filter filter, char *type ) { // Result to return mlt_filter result = NULL; // Miscelaneous variable int i = 0; int type_len = strlen( type ); // Get the properties of the data show filter mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); // Get the profile properties mlt_properties profile_properties = mlt_properties_get_data( filter_properties, "profile_properties", NULL ); // Obtain the profile_properties if we haven't already if ( profile_properties == NULL ) { char temp[ 512 ]; // Get the profile requested char *profile = mlt_properties_get( filter_properties, "resource" ); // If none is specified, pick up the default for this normalisation if ( profile == NULL ) sprintf( temp, "%s/feeds/%s/data_fx.properties", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ) ); else if ( strchr( profile, '%' ) ) sprintf( temp, "%s/feeds/%s/%s", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ), strchr( profile, '%' ) + 1 ); else { strncpy( temp, profile, sizeof( temp ) ); temp[ sizeof( temp ) - 1 ] = '\0'; } // Load the specified profile or use the default profile_properties = mlt_properties_load( temp ); // Store for later retrieval mlt_properties_set_data( filter_properties, "profile_properties", profile_properties, 0, ( mlt_destructor )mlt_properties_close, NULL ); } if ( profile_properties != NULL ) { for ( i = 0; i < mlt_properties_count( profile_properties ); i ++ ) { char *name = mlt_properties_get_name( profile_properties, i ); char *value = mlt_properties_get_value( profile_properties, i ); if ( result == NULL && !strcmp( name, type ) && result == NULL ) result = mlt_factory_filter( mlt_service_profile( MLT_FILTER_SERVICE( filter ) ), value, NULL ); else if ( result != NULL && !strncmp( name, type, type_len ) && name[ type_len ] == '.' ) mlt_properties_set( MLT_FILTER_PROPERTIES( result ), name + type_len + 1, value ); else if ( result != NULL ) break; } } return result; }
void mlt_cache_purge( mlt_cache cache, void *object ) { pthread_mutex_lock( &cache->mutex ); if ( cache && object ) { int i, j; void **alt = cache->current == cache->A ? cache->B : cache->A; for ( i = 0, j = 0; i < cache->count; i++ ) { void *o = cache->current[ i ]; if ( o == object ) { pthread_mutex_unlock( &cache->mutex ); cache_object_close( cache, o, NULL ); pthread_mutex_lock( &cache->mutex ); } else { alt[ j++ ] = o; } } cache->count = j; cache->current = alt; // Remove the object's data from the active list regardless of refcount char key[19]; sprintf( key, "%p", object ); mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL ); if ( item && item->destructor ) { item->destructor( item->data ); item->data = NULL; item->destructor = NULL; mlt_properties_set_data( cache->active, key, NULL, 0, NULL, NULL ); } // Remove the object's items from the garbage collection regardless of refcount i = mlt_properties_count( cache->garbage ); while ( i-- ) { item = mlt_properties_get_data_at( cache->garbage, i, NULL ); if ( object == item->object && item->destructor ) { sprintf( key, "%p", item->data ); item->destructor( item->data ); item->data = NULL; item->destructor = NULL; mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL ); } } } pthread_mutex_unlock( &cache->mutex ); }
static void query_presets() { mlt_properties presets = mlt_repository_presets(); fprintf( stdout, "---\npresets:\n" ); if ( presets ) { int j; for ( j = 0; j < mlt_properties_count( presets ); j++ ) fprintf( stdout, " - %s\n", mlt_properties_get_name( presets, j ) ); } fprintf( stdout, "...\n" ); mlt_properties_close( presets ); }
std::ostream& operator <<(std::ostream& os, mlt_properties props) { int count = mlt_properties_count(props); os<<"{"<<endl; for ( int i=0; i<count; i++) { char buf[1024]; const char* name = mlt_properties_get_name(props, i); snprintf(buf, sizeof(buf), "%s: %s\n", name, mlt_properties_get(props, name)); os << buf ; } os<<"}"<<endl; return os; }
static void query_profiles() { mlt_properties profiles = mlt_profile_list(); fprintf( stdout, "---\nprofiles:\n" ); if ( profiles ) { int j; for ( j = 0; j < mlt_properties_count( profiles ); j++ ) fprintf( stdout, " - %s\n", mlt_properties_get_name( profiles, j ) ); } fprintf( stdout, "...\n" ); mlt_properties_close( profiles ); }
void mlt_service_cache_purge( mlt_service self ) { mlt_properties caches = mlt_properties_get_data( mlt_global_properties(), "caches", NULL ); if ( caches ) { int i = mlt_properties_count( caches ); while ( i-- ) { mlt_cache_purge( mlt_properties_get_data_at( caches, i, NULL ), self ); mlt_properties_set_data( mlt_global_properties(), mlt_properties_get_name( caches, i ), NULL, 0, NULL, NULL ); } } }
static void load_filenames( producer_qimage self, mlt_properties properties ) { char *filename = mlt_properties_get( properties, "resource" ); self->filenames = mlt_properties_new( ); if (!load_svg( self, properties, filename ) && !load_sequence( self, properties, filename ) && !load_sequence2( self, properties, filename ) && !load_folder( self, properties, filename ) ) { mlt_properties_set( self->filenames, "0", filename ); } self->count = mlt_properties_count( self->filenames ); }
static void load_filenames( producer_pixbuf self, mlt_properties properties ) { char *filename = mlt_properties_get( properties, "resource" ); self->filenames = mlt_properties_new( ); if (!load_svg( self, properties, filename ) && !load_sequence_querystring( self, properties, filename ) && !load_sequence_sprintf( self, properties, filename ) && !load_sequence_deprecated( self, properties, filename ) && !load_folder( self, properties, filename ) ) { mlt_properties_set( self->filenames, "0", filename ); } self->count = mlt_properties_count( self->filenames ); }
static void check_thread_safe( mlt_properties properties, const char *name ) { char dirname[PATH_MAX]; snprintf( dirname, PATH_MAX, "%s/frei0r/not_thread_safe.txt", mlt_environment( "MLT_DATA" ) ); mlt_properties not_thread_safe = mlt_properties_load( dirname ); int i; for ( i = 0; i < mlt_properties_count( not_thread_safe ); i++ ) { if ( strcmp( name, mlt_properties_get_name( not_thread_safe, i ) ) == 0 ) { mlt_properties_set_int( properties, "_not_thread_safe", 1 ); break; } } mlt_properties_close( not_thread_safe ); }
static void list_presets( mlt_properties properties, const char *path, const char *dirname ) { DIR *dir = opendir( dirname ); if ( dir ) { struct dirent *de = readdir( dir ); char fullname[ PATH_MAX ]; while ( de != NULL ) { if ( de->d_name[0] != '.' && de->d_name[strlen( de->d_name ) - 1] != '~' ) { struct stat info; snprintf( fullname, sizeof(fullname), "%s/%s", dirname, de->d_name ); stat( fullname, &info ); if ( S_ISDIR( info.st_mode ) ) { // recurse into subdirectories char sub[ PATH_MAX ]; if ( path ) snprintf( sub, sizeof(sub), "%s/%s", path, de->d_name ); else strncpy( sub, de->d_name, sizeof(sub) ); list_presets( properties, sub, fullname ); } else { // load the preset mlt_properties preset = mlt_properties_load( fullname ); if ( preset && mlt_properties_count( preset ) ) { snprintf( fullname, 1024, "%s/%s", path, de->d_name ); mlt_properties_set_data( properties, fullname, preset, 0, (mlt_destructor) mlt_properties_close, NULL ); } } } de = readdir( dir ); } closedir( dir ); } }
mlt_properties mlt_profile_list( ) { char *filename = NULL; const char *prefix = getenv( "MLT_PROFILES_PATH" ); mlt_properties properties = mlt_properties_new(); mlt_properties dir = mlt_properties_new(); int sort = 1; const char *wildcard = NULL; int i; // Load from $datadir/mlt/profiles if no env var if ( prefix == NULL ) { prefix = mlt_environment( "MLT_DATA" ); filename = calloc( 1, strlen( prefix ) + strlen( PROFILES_DIR ) + 1 ); strcpy( filename, prefix ); strcat( filename, PROFILES_DIR ); prefix = filename; } mlt_properties_dir_list( dir, prefix, wildcard, sort ); for ( i = 0; i < mlt_properties_count( dir ); i++ ) { char *filename = mlt_properties_get_value( dir, i ); char *profile_name = basename( filename ); if ( profile_name[0] != '.' && strcmp( profile_name, "Makefile" ) && profile_name[ strlen( profile_name ) - 1 ] != '~' ) { mlt_properties profile = mlt_properties_load( filename ); if ( profile ) { mlt_properties_set_data( properties, profile_name, profile, 0, (mlt_destructor) mlt_properties_close, NULL ); } } } mlt_properties_close( dir ); if ( filename ) free( filename ); return properties; }
static int load_sequence_sprintf( producer_qimage self, mlt_properties properties, const char *filename ) { int result = 0; // Obtain filenames with pattern if ( strchr( filename, '%' ) != NULL ) { // handle picture sequences int i = mlt_properties_get_int( properties, "begin" ); int gap = 0; char full[1024]; int keyvalue = 0; char key[ 50 ]; while ( gap < 100 ) { struct stat buf; snprintf( full, 1023, filename, i ++ ); if ( stat( full, &buf ) == 0 ) { sprintf( key, "%d", keyvalue ++ ); mlt_properties_set( self->filenames, key, full ); gap = 0; } else { gap ++; } } if ( mlt_properties_count( self->filenames ) > 0 ) { mlt_properties_set_int( properties, "ttl", 1 ); result = 1; } } return result; }
static int is_service_hidden(mlt_repository repo, mlt_service_type type, const char *service_name ) { mlt_properties metadata = NULL; mlt_properties tags = NULL; metadata = mlt_repository_metadata(repo, type, service_name); if( metadata ) { tags = mlt_properties_get_data( metadata, "tags", NULL ); if( tags ) { int k; for ( k = 0; k < mlt_properties_count( tags ); k++ ) { const char* value = mlt_properties_get_value(tags, k); if( !strcmp("Hidden", value) ) { return 1; } } } } return 0; }
mlt_producer producer_framebuffer_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { if ( !arg ) return NULL; mlt_producer producer = NULL; producer = calloc( 1, sizeof( struct mlt_producer_s ) ); if ( !producer ) return NULL; if ( mlt_producer_init( producer, NULL ) ) { free( producer ); return NULL; } // Wrap loader mlt_producer real_producer; // Check if a speed was specified. /** * Speed must be appended to the filename with '?'. To play your video at 50%: melt framebuffer:my_video.mpg?0.5 * Stroboscope effect can be obtained by adding a stobe=x parameter, where x is the number of frames that will be ignored. * You can play the movie backwards by adding reverse=1 * You can freeze the clip at a determined position by adding freeze=frame_pos add freeze_after=1 to freeze only paste position or freeze_before to freeze before it **/ double speed = 0.0; char *props = strdup( arg ); char *ptr = strrchr( props, '?' ); if ( ptr ) { speed = atof( ptr + 1 ); if ( speed != 0.0 ) // If speed was valid, then strip it and the delimiter. // Otherwise, an invalid speed probably means this '?' was not a delimiter. *ptr = '\0'; } real_producer = mlt_factory_producer( profile, "abnormal", props ); free( props ); if (speed == 0.0) speed = 1.0; if ( producer != NULL && real_producer != NULL) { // Get the properties of this producer mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_properties_set( properties, "resource", arg); // Store the producer and fitler mlt_properties_set_data( properties, "producer", real_producer, 0, ( mlt_destructor )mlt_producer_close, NULL ); // Grab some stuff from the real_producer mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( real_producer ), "length, width, height, aspect_ratio" ); if ( speed < 0 ) { speed = -speed; mlt_properties_set_int( properties, "reverse", 1 ); } if ( speed != 1.0 ) { double real_length = ( (double) mlt_producer_get_length( real_producer ) ) / speed; mlt_properties_set_position( properties, "length", real_length ); mlt_properties real_properties = MLT_PRODUCER_PROPERTIES( real_producer ); const char* service = mlt_properties_get( real_properties, "mlt_service" ); if ( service && !strcmp( service, "avformat" ) ) { int n = mlt_properties_count( real_properties ); int i; for ( i = 0; i < n; i++ ) { if ( strstr( mlt_properties_get_name( real_properties, i ), "stream.frame_rate" ) ) { double source_fps = mlt_properties_get_double( real_properties, mlt_properties_get_name( real_properties, i ) ); if ( source_fps > mlt_profile_fps( profile ) ) { mlt_properties_set_double( real_properties, "force_fps", source_fps * speed ); mlt_properties_set_position( real_properties, "length", real_length ); mlt_properties_set_position( real_properties, "out", real_length - 1 ); speed = 1.0; } break; } } } } mlt_properties_set_position( properties, "out", mlt_producer_get_length( producer ) - 1 ); // Since we control the seeking, prevent it from seeking on its own mlt_producer_set_speed( real_producer, 0 ); mlt_producer_set_speed( producer, speed ); // Override the get_frame method producer->get_frame = producer_get_frame; } else { if ( producer ) mlt_producer_close( producer ); if ( real_producer ) mlt_producer_close( real_producer ); producer = NULL; } return producer; }
int mlt_producer_optimise( mlt_producer self ) { int error = 1; mlt_parser parser = mlt_parser_new( ); if ( parser != NULL ) { int i = 0, j = 0, k = 0; mlt_properties properties = mlt_parser_properties( parser ); mlt_properties producers = mlt_properties_new( ); mlt_deque stack = mlt_deque_init( ); mlt_properties_set_data( properties, "producers", producers, 0, ( mlt_destructor )mlt_properties_close, NULL ); mlt_properties_set_data( properties, "stack", stack, 0, ( mlt_destructor )mlt_deque_close, NULL ); parser->on_start_producer = on_start_producer; parser->on_start_track = on_start_track; parser->on_end_track = on_end_track; parser->on_start_multitrack = on_start_multitrack; parser->on_end_multitrack = on_end_multitrack; push( parser, 0, 0, 0 ); mlt_parser_start( parser, MLT_PRODUCER_SERVICE( self ) ); free( pop( parser ) ); for ( k = 0; k < mlt_properties_count( producers ); k ++ ) { char *name = mlt_properties_get_name( producers, k ); int count = 0; int clones = 0; int max_clones = 0; mlt_producer producer = mlt_properties_get_data_at( producers, k, &count ); if ( producer != NULL && count > 1 ) { clip_references *refs = mlt_properties_get_data( properties, name, &count ); for ( i = 0; i < count; i ++ ) { clones = 0; for ( j = i + 1; j < count; j ++ ) { if ( intersect( &refs[ i ], &refs[ j ] ) ) { clones ++; mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( refs[ j ].cut ), "_clone", clones ); } } if ( clones > max_clones ) max_clones = clones; } for ( i = 0; i < count; i ++ ) { mlt_producer cut = refs[ i ].cut; if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone" ) == -1 ) mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone", 0 ); } mlt_producer_set_clones( producer, max_clones ); } else if ( producer != NULL ) { clip_references *refs = mlt_properties_get_data( properties, name, &count ); for ( i = 0; i < count; i ++ ) { mlt_producer cut = refs[ i ].cut; mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone", 0 ); } mlt_producer_set_clones( producer, 0 ); } } mlt_parser_close( parser ); } return error; }
static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int index ) { int result = 1; mlt_producer self = service != NULL ? service->child : NULL; if ( self != NULL && !mlt_producer_is_cut( self ) ) { // Get the properties of this producer mlt_properties properties = MLT_PRODUCER_PROPERTIES( self ); // Determine eof handling char *eof = mlt_properties_get( MLT_PRODUCER_PROPERTIES( self ), "eof" ); // Get the speed of the producer double speed = mlt_producer_get_speed( self ); // We need to use the clone if it's specified mlt_producer clone = mlt_properties_get_data( properties, "use_clone", NULL ); // If no clone is specified, use self clone = clone == NULL ? self : clone; // A properly instatiated producer will have a get_frame method... if ( self->get_frame == NULL || ( eof && !strcmp( eof, "continue" ) && mlt_producer_position( self ) > mlt_producer_get_out( self ) ) ) { // Generate a test frame *frame = mlt_frame_init( service ); // Set the position result = mlt_frame_set_position( *frame, mlt_producer_position( self ) ); // Mark as a test card mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", 1 ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_audio", 1 ); // Calculate the next position mlt_producer_prepare_next( self ); } else { // Get the frame from the implementation result = self->get_frame( clone, frame, index ); } // Copy the fps and speed of the producer onto the frame properties = MLT_FRAME_PROPERTIES( *frame ); mlt_properties_set_double( properties, "_speed", speed ); mlt_properties_set_int( properties, "test_audio", mlt_frame_is_test_audio( *frame ) ); mlt_properties_set_int( properties, "test_image", mlt_frame_is_test_card( *frame ) ); if ( mlt_properties_get_data( properties, "_producer", NULL ) == NULL ) mlt_properties_set_data( properties, "_producer", service, 0, NULL, NULL ); } else if ( self != NULL ) { // Get the speed of the cut double speed = mlt_producer_get_speed( self ); // Get the parent of the cut mlt_producer parent = mlt_producer_cut_parent( self ); // Get the properties of the parent mlt_properties parent_properties = MLT_PRODUCER_PROPERTIES( parent ); // Get the properties of the cut mlt_properties properties = MLT_PRODUCER_PROPERTIES( self ); // Determine the clone index int clone_index = mlt_properties_get_int( properties, "_clone" ); // Determine the clone to use mlt_producer clone = self; if ( clone_index > 0 ) { char key[ 25 ]; sprintf( key, "_clone.%d", clone_index - 1 ); clone = mlt_properties_get_data( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( self ) ), key, NULL ); if ( clone == NULL ) mlt_log( service, MLT_LOG_ERROR, "requested clone doesn't exist %d\n", clone_index ); clone = clone == NULL ? self : clone; } else { clone = parent; } // We need to seek to the correct position in the clone mlt_producer_seek( clone, mlt_producer_get_in( self ) + mlt_properties_get_int( properties, "_position" ) ); // Assign the clone property to the parent mlt_properties_set_data( parent_properties, "use_clone", clone, 0, NULL, NULL ); // Now get the frame from the parents service result = mlt_service_get_frame( MLT_PRODUCER_SERVICE( parent ), frame, index ); // We're done with the clone now mlt_properties_set_data( parent_properties, "use_clone", NULL, 0, NULL, NULL ); // This is useful and required by always_active transitions to determine in/out points of the cut if ( mlt_properties_get_data( MLT_FRAME_PROPERTIES( *frame ), "_producer", NULL ) == MLT_PRODUCER_SERVICE( parent ) ) mlt_properties_set_data( MLT_FRAME_PROPERTIES( *frame ), "_producer", self, 0, NULL, NULL ); mlt_properties_set_double( MLT_FRAME_PROPERTIES( *frame ), "_speed", speed ); mlt_producer_prepare_next( self ); } else { *frame = mlt_frame_init( service ); result = 0; } // Pass on all meta properties from the producer/cut on to the frame if ( *frame != NULL && self != NULL ) { int i = 0; mlt_properties p_props = MLT_PRODUCER_PROPERTIES( self ); mlt_properties f_props = MLT_FRAME_PROPERTIES( *frame ); mlt_properties_lock( p_props ); int count = mlt_properties_count( p_props ); for ( i = 0; i < count; i ++ ) { char *name = mlt_properties_get_name( p_props, i ); if ( !strncmp( name, "meta.", 5 ) ) mlt_properties_set( f_props, name, mlt_properties_get_value( p_props, i ) ); else if ( !strncmp( name, "set.", 4 ) ) mlt_properties_set( f_props, name + 4, mlt_properties_get_value( p_props, i ) ); } mlt_properties_unlock( p_props ); } return result; }
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; }
static void foreach_consumer_init( mlt_consumer consumer ) { const char *resource = mlt_properties_get( MLT_CONSUMER_PROPERTIES(consumer), "resource" ); mlt_properties properties = mlt_properties_parse_yaml( resource ); char key[20]; int index = 0; if ( mlt_properties_get_data( MLT_CONSUMER_PROPERTIES(consumer), "0", NULL ) ) { // Properties set directly by application mlt_properties p; if ( properties ) mlt_properties_close( properties ); properties = MLT_CONSUMER_PROPERTIES(consumer); do { snprintf( key, sizeof(key), "%d", index ); if ( ( p = mlt_properties_get_data( properties, key, NULL ) ) ) generate_consumer( consumer, p, index++ ); } while ( p ); } else if ( properties && mlt_properties_get_data( properties, "0", NULL ) ) { // YAML file supplied mlt_properties p; do { snprintf( key, sizeof(key), "%d", index ); if ( ( p = mlt_properties_get_data( properties, key, NULL ) ) ) generate_consumer( consumer, p, index++ ); } while ( p ); mlt_properties_close( properties ); } else { // properties file supplied or properties on this consumer const char *s; if ( properties ) mlt_properties_close( properties ); if ( resource ) properties = mlt_properties_load( resource ); else properties = MLT_CONSUMER_PROPERTIES( consumer ); do { snprintf( key, sizeof(key), "%d", index ); if ( ( s = mlt_properties_get( properties, key ) ) ) { mlt_properties p = mlt_properties_new(); int i, count; if ( !p ) break; mlt_properties_set( p, "mlt_service", mlt_properties_get( properties, key ) ); snprintf( key, sizeof(key), "%d.", index ); count = mlt_properties_count( properties ); for ( i = 0; i < count; i++ ) { char *name = mlt_properties_get_name( properties, i ); if ( !strncmp( name, key, strlen(key) ) ) mlt_properties_set( p, name + strlen(key), mlt_properties_get_value( properties, i ) ); } generate_consumer( consumer, p, index++ ); mlt_properties_close( p ); } } while ( s ); if ( resource ) mlt_properties_close( properties ); } }
void TransitionHandler::updateTransitionParams(QString type, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml) { QScopedPointer<Mlt::Field> field(m_tractor->field()); field->lock(); mlt_service nextservice = mlt_service_get_producer(field->get_service()); mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice); QString mlt_type = mlt_properties_get(properties, "mlt_type"); QString resource = mlt_properties_get(properties, "mlt_service"); int in_pos = (int) in.frames(m_fps); int out_pos = (int) out.frames(m_fps) - 1; while (mlt_type == QLatin1String("transition")) { mlt_transition tr = (mlt_transition) nextservice; int currentTrack = mlt_transition_get_b_track(tr); int currentBTrack = mlt_transition_get_a_track(tr); int currentIn = (int) mlt_transition_get_in(tr); int currentOut = (int) mlt_transition_get_out(tr); // //qDebug()<<"Looking for transition : " << currentIn <<'x'<<currentOut<< ", OLD oNE: "<<in_pos<<'x'<<out_pos; if (resource == type && b_track == currentTrack && currentIn == in_pos && currentOut == out_pos) { QMap<QString, QString> map = getTransitionParamsFromXml(xml); QMap<QString, QString>::Iterator it; QString key; mlt_properties transproperties = MLT_TRANSITION_PROPERTIES(tr); QString currentId = mlt_properties_get(transproperties, "kdenlive_id"); if (currentId != xml.attribute(QStringLiteral("id"))) { // The transition ID is not the same, so reset all properties mlt_properties_set(transproperties, "kdenlive_id", xml.attribute(QStringLiteral("id")).toUtf8().constData()); // Cleanup previous properties QStringList permanentProps; permanentProps << QStringLiteral("factory") << QStringLiteral("kdenlive_id") << QStringLiteral("mlt_service") << QStringLiteral("mlt_type") << QStringLiteral("in"); permanentProps << QStringLiteral("out") << QStringLiteral("a_track") << QStringLiteral("b_track"); for (int i = 0; i < mlt_properties_count(transproperties); ++i) { QString propName = mlt_properties_get_name(transproperties, i); if (!propName.startsWith('_') && ! permanentProps.contains(propName)) { mlt_properties_set(transproperties, propName.toUtf8().constData(), ""); } } } mlt_properties_set_int(transproperties, "force_track", xml.attribute(QStringLiteral("force_track")).toInt()); mlt_properties_set_int(transproperties, "automatic", xml.attribute(QStringLiteral("automatic"), QStringLiteral("0")).toInt()); if (currentBTrack != a_track) { mlt_properties_set_int(transproperties, "a_track", a_track); } for (it = map.begin(); it != map.end(); ++it) { key = it.key(); mlt_properties_set(transproperties, key.toUtf8().constData(), it.value().toUtf8().constData()); ////qDebug() << " ------ UPDATING TRANS PARAM: " << key.toUtf8().constData() << ": " << it.value().toUtf8().constData(); //filter->set("kdenlive_id", id); } break; } nextservice = mlt_service_producer(nextservice); if (nextservice == NULL) break; properties = MLT_SERVICE_PROPERTIES(nextservice); mlt_type = mlt_properties_get(properties, "mlt_type"); resource = mlt_properties_get(properties, "mlt_service"); } field->unlock(); //askForRefresh(); //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1); }
static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Error we will return int error = 0; // We will get the 'b frame' from the frame stack mlt_frame b_frame = mlt_frame_pop_frame( frame ); // Get the watermark transition object mlt_transition transition = mlt_frame_pop_service( frame ); // Get the properties of the transitionfin mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); // Get the properties of the a frame mlt_properties a_props = MLT_FRAME_PROPERTIES( frame ); mlt_service_lock( MLT_TRANSITION_SERVICE( transition ) ); // Get the composite from the transition mlt_transition composite = mlt_properties_get_data( properties, "composite", NULL ); // Look for the first filter mlt_filter filter = mlt_properties_get_data( properties, "_filter_0", NULL ); // Get the position mlt_position position = mlt_transition_get_position( transition, frame ); // Create a composite if we don't have one if ( composite == NULL ) { // Create composite via the factory mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) ); composite = mlt_factory_transition( profile, "composite", NULL ); // If we have one if ( composite != NULL ) { // Get the properties mlt_properties composite_properties = MLT_TRANSITION_PROPERTIES( composite ); // We want to ensure that we don't get a wobble... //mlt_properties_set_int( composite_properties, "distort", 1 ); mlt_properties_set_int( composite_properties, "progressive", 1 ); // Pass all the composite. properties on the transition down mlt_properties_pass( composite_properties, properties, "composite." ); // Register the composite for reuse/destruction mlt_properties_set_data( properties, "composite", composite, 0, ( mlt_destructor )mlt_transition_close, NULL ); } } else { // Pass all current properties down mlt_properties composite_properties = MLT_TRANSITION_PROPERTIES( composite ); mlt_properties_pass( composite_properties, properties, "composite." ); } // Create filters if ( filter == NULL ) { // Loop Variable int i = 0; // Number of filters created int count = 0; // Loop for all properties for ( i = 0; i < mlt_properties_count( properties ); i ++ ) { // Get the name of this property char *name = mlt_properties_get_name( properties, i ); // If the name does not contain a . and matches filter if ( strchr( name, '.' ) == NULL && !strncmp( name, "filter", 6 ) ) { // Get the filter constructor char *value = mlt_properties_get_value( properties, i ); // Create an instance if ( create_instance( transition, name, value, count ) == 0 ) count ++; } } // Look for the first filter again filter = mlt_properties_get_data( properties, "_filter_0", NULL ); } else { // Pass all properties down mlt_filter temp = NULL; // Loop Variable int i = 0; // Number of filters found int count = 0; // Loop for all properties for ( i = 0; i < mlt_properties_count( properties ); i ++ ) { // Get the name of this property char *name = mlt_properties_get_name( properties, i ); // If the name does not contain a . and matches filter if ( strchr( name, '.' ) == NULL && !strncmp( name, "filter", 6 ) ) { // Strings to hold the id and pass down key char id[ 256 ]; char key[ 256 ]; // Construct id and key sprintf( id, "_filter_%d", count ); sprintf( key, "%s.", name ); // Get the filter temp = mlt_properties_get_data( properties, id, NULL ); if ( temp != NULL ) { mlt_properties_pass( MLT_FILTER_PROPERTIES( temp ), properties, key ); count ++; } } } } mlt_properties_set_int( a_props, "width", *width ); mlt_properties_set_int( a_props, "height", *height ); // Only continue if we have both filter and composite if ( composite != NULL ) { // Get the resource of this filter (could be a shape [rectangle/circle] or an alpha provider of choice const char *resource = mlt_properties_get( properties, "resource" ); // Get the old resource in case it's changed char *old_resource = mlt_properties_get( properties, "_old_resource" ); // String to hold the filter to query on char id[ 256 ]; // Index to hold the count int i = 0; // We will get the 'b frame' from the composite only if it's NULL (region filter) if ( b_frame == NULL ) { // Copy the region b_frame = composite_copy_region( composite, frame, position ); // Ensure a destructor char *name = mlt_properties_get( properties, "_unique_id" ); mlt_properties_set_data( a_props, name, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); } // Properties of the B framr mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); // filter_only prevents copying the alpha channel of the shape to the output frame // by compositing filtered frame over itself if ( mlt_properties_get_int( properties, "filter_only" ) ) { char *name = mlt_properties_get( properties, "_unique_id" ); frame = composite_copy_region( composite, b_frame, position ); mlt_properties_set_data( b_props, name, frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); } // Make sure the filter is in the correct position while ( filter != NULL ) { // Stack this filter if ( mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "off" ) == 0 ) mlt_filter_process( filter, b_frame ); // Generate the key for the next sprintf( id, "_filter_%d", ++ i ); // Get the next filter filter = mlt_properties_get_data( properties, id, NULL ); } // Allow filters to be attached to a region filter filter = mlt_properties_get_data( properties, "_region_filter", NULL ); if ( filter != NULL ) mlt_service_apply_filters( MLT_FILTER_SERVICE( filter ), b_frame, 0 ); // Hmm - this is probably going to go wrong.... mlt_frame_set_position( frame, position ); // Get the b frame and process with composite if successful mlt_transition_process( composite, frame, b_frame ); // If we have a shape producer copy the alpha mask from the shape frame to the b_frame if ( strcmp( resource, "rectangle" ) != 0 ) { // Get the producer from the transition mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL ); // If We have no producer then create one if ( producer == NULL || ( old_resource != NULL && strcmp( resource, old_resource ) ) ) { // Get the factory producer service char *factory = mlt_properties_get( properties, "factory" ); // Store the old resource mlt_properties_set( properties, "_old_resource", resource ); // Special case circle resource if ( strcmp( resource, "circle" ) == 0 ) resource = "pixbuf:<svg width='100' height='100'><circle cx='50' cy='50' r='50' fill='black'/></svg>"; // Create the producer mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) ); producer = mlt_factory_producer( profile, factory, resource ); // If we have one if ( producer != NULL ) { // Get the producer properties mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); // Ensure that we loop mlt_properties_set( producer_properties, "eof", "loop" ); // Now pass all producer. properties on the transition down mlt_properties_pass( producer_properties, properties, "producer." ); // Register the producer for reuse/destruction mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL ); } } // Now use the shape producer if ( producer != NULL ) { // We will get the alpha frame from the producer mlt_frame shape_frame = NULL; // Make sure the producer is in the correct position mlt_producer_seek( producer, position ); // Get the shape frame if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &shape_frame, 0 ) == 0 ) { // Ensure that the shape frame will be closed mlt_properties_set_data( b_props, "shape_frame", shape_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); if ( mlt_properties_get_int(properties, "holecolor") ) { mlt_properties_set_int(b_props, "holecolor", mlt_properties_get_int(properties,"holecolor")); } // Specify the callback for evaluation b_frame->get_alpha_mask = filter_get_alpha_mask; } } } // Get the image error = mlt_frame_get_image( frame, image, format, width, height, 0 ); } mlt_service_unlock( MLT_TRANSITION_SERVICE( transition ) ); return error; }
static mlt_producer create_producer( mlt_profile profile, char *file ) { mlt_producer result = NULL; // 1st Line - check for service:resource handling if ( strchr( file, ':' ) ) { char *temp = strdup( file ); char *service = temp; char *resource = strchr( temp, ':' ); *resource ++ = '\0'; result = mlt_factory_producer( profile, service, resource ); free( temp ); } // 2nd Line preferences if ( result == NULL ) { int i = 0; char *lookup = strdup( file ); char *p = lookup; // Make backup of profile for determining if we need to use 'consumer' producer. mlt_profile backup_profile = mlt_profile_clone( profile ); // We only need to load the dictionary once if ( dictionary == NULL ) { char temp[ 1024 ]; sprintf( temp, "%s/core/loader.dict", mlt_environment( "MLT_DATA" ) ); dictionary = mlt_properties_load( temp ); mlt_factory_register_for_clean_up( dictionary, ( mlt_destructor )mlt_properties_close ); } // Convert the lookup string to lower case while ( *p ) { *p = tolower( *p ); p ++; } // Iterate through the dictionary for ( i = 0; result == NULL && i < mlt_properties_count( dictionary ); i ++ ) { char *name = mlt_properties_get_name( dictionary, i ); if ( fnmatch( name, lookup, 0 ) == 0 ) result = create_from( profile, file, mlt_properties_get_value( dictionary, i ) ); } // Check if the producer changed the profile - xml does this. // The consumer producer does not handle frame rate differences. if ( result && backup_profile->is_explicit && ( profile->width != backup_profile->width || profile->height != backup_profile->height || profile->sample_aspect_num != backup_profile->sample_aspect_num || profile->sample_aspect_den != backup_profile->sample_aspect_den || profile->colorspace != backup_profile->colorspace ) ) { // Restore the original profile attributes. profile->display_aspect_den = backup_profile->display_aspect_den; profile->display_aspect_num = backup_profile->display_aspect_num; profile->frame_rate_den = backup_profile->frame_rate_den; profile->frame_rate_num = backup_profile->frame_rate_num; profile->height = backup_profile->height; profile->progressive = backup_profile->progressive; profile->sample_aspect_den = backup_profile->sample_aspect_den; profile->sample_aspect_num = backup_profile->sample_aspect_num; profile->width = backup_profile->width; // Use the 'consumer' producer. mlt_producer_close( result ); result = mlt_factory_producer( profile, "consumer", file ); } mlt_profile_close( backup_profile ); free( lookup ); } // Finally, try just loading as service if ( result == NULL ) result = mlt_factory_producer( profile, file, NULL ); return result; }
static int process_feed( mlt_properties feed, mlt_filter filter, mlt_frame frame ) { // Error return int error = 1; // Get the properties of the data show filter mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); // Get the type requested by the feeding filter char *type = mlt_properties_get( feed, "type" ); // Fetch the filter associated to this type mlt_filter requested = mlt_properties_get_data( filter_properties, type, NULL ); // If it doesn't exist, then create it now if ( requested == NULL ) { // Source filter from profile requested = obtain_filter( filter, type ); // Store it on the properties for subsequent retrieval/destruction mlt_properties_set_data( filter_properties, type, requested, 0, ( mlt_destructor )mlt_filter_close, NULL ); } // If we have one, then process it now... if ( requested != NULL ) { int i = 0; mlt_properties properties = MLT_FILTER_PROPERTIES( requested ); static const char *prefix = "properties."; int len = strlen( prefix ); // Determine if this is an absolute or relative feed int absolute = mlt_properties_get_int( feed, "absolute" ); // Make do with what we have int length = !absolute ? mlt_properties_get_int( feed, "out" ) - mlt_properties_get_int( feed, "in" ) + 1 : mlt_properties_get_int( feed, "out" ) + 1; // Repeat period int period = mlt_properties_get_int( properties, "period" ); period = period == 0 ? 1 : period; // Pass properties from feed into requested for ( i = 0; i < mlt_properties_count( properties ); i ++ ) { char *name = mlt_properties_get_name( properties, i ); char *key = mlt_properties_get_value( properties, i ); if ( !strncmp( name, prefix, len ) ) { if ( !strncmp( name + len, "length[", 7 ) ) { mlt_properties_set_position( properties, key, ( length - period ) / period ); } else { char *value = mlt_properties_get( feed, name + len ); if ( value != NULL ) { // check for metadata keywords in metadata markup if user requested so if ( mlt_properties_get_int( filter_properties, "dynamic" ) == 1 && !strcmp( name + strlen( name ) - 6, "markup") ) { // Find keywords which should be surrounded by '#', like: #title# char* keywords = strtok( value, "#" ); char result[512] = ""; // XXX: how much is enough? int ct = 0; int fromStart = ( value[0] == '#' ) ? 1 : 0; while ( keywords != NULL ) { if ( ct % 2 == fromStart ) { // backslash in front of # suppresses substitution if ( keywords[ strlen( keywords ) -1 ] == '\\' ) { // keep characters except backslash strncat( result, keywords, sizeof( result ) - strlen( result ) - 2 ); strcat( result, "#" ); ct++; } else { strncat( result, keywords, sizeof( result ) - strlen( result ) - 1 ); } } else if ( !strcmp( keywords, "timecode" ) ) { // special case: replace #timecode# with current frame timecode mlt_position frames = mlt_properties_get_position( feed, "position" ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); char *s = mlt_properties_frames_to_time( properties, frames, mlt_time_smpte_df ); if ( s ) strncat( result, s, sizeof( result ) - strlen( result ) - 1 ); } else if ( !strcmp( keywords, "frame" ) ) { // special case: replace #frame# with current frame number int pos = mlt_properties_get_int( feed, "position" ); char s[12]; snprintf( s, sizeof(s) - 1, "%d", pos ); s[sizeof( s ) - 1] = '\0'; strncat( result, s, sizeof( result ) - strlen( result ) - 1 ); } else { // replace keyword with metadata value char *metavalue = metadata_value( MLT_FRAME_PROPERTIES( frame ), keywords ); strncat( result, metavalue ? metavalue : "-", sizeof( result ) - strlen( result ) -1 ); } keywords = strtok( NULL, "#" ); ct++; } mlt_properties_set( properties, key, (char*) result ); } else mlt_properties_set( properties, key, value ); } } } } // Set the original position on the frame if ( absolute == 0 ) mlt_frame_set_position( frame, mlt_properties_get_int( feed, "position" ) - mlt_properties_get_int( feed, "in" ) ); else mlt_frame_set_position( frame, mlt_properties_get_int( feed, "position" ) ); // Process the filter mlt_filter_process( requested, frame ); // Should be ok... error = 0; } return error; }
void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor ) { char unique[ 256 ]; sprintf( unique, "%08d", mlt_properties_count( global_properties ) ); mlt_properties_set_data( global_properties, unique, ptr, 0, destructor, NULL ); }
static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track ) { mlt_tractor self = parent->child; // We only respond to the first track requests if ( track == 0 && self->producer != NULL ) { int i = 0; int done = 0; mlt_frame temp = NULL; int count = 0; int image_count = 0; // Get the properties of the parent producer mlt_properties properties = MLT_PRODUCER_PROPERTIES( parent ); // Try to obtain the multitrack associated to the tractor mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL ); // Or a specific producer mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL ); // Determine whether this tractor feeds to the consumer or stops here int global_feed = mlt_properties_get_int( properties, "global_feed" ); // If we don't have one, we're in trouble... if ( multitrack != NULL ) { // The output frame will hold the 'global' data feeds (ie: those which are targetted for the final frame) mlt_deque data_queue = mlt_deque_init( ); // Used to garbage collect all frames char label[ 30 ]; // Get the id of the tractor char *id = mlt_properties_get( properties, "_unique_id" ); // Will be used to store the frame properties object mlt_properties frame_properties = NULL; // We'll store audio and video frames to use here mlt_frame audio = NULL; mlt_frame video = NULL; mlt_frame first_video = NULL; // Temporary properties mlt_properties temp_properties = NULL; // Get the multitrack's producer mlt_producer target = MLT_MULTITRACK_PRODUCER( multitrack ); mlt_producer_seek( target, mlt_producer_frame( parent ) ); mlt_producer_set_speed( target, mlt_producer_get_speed( parent ) ); // We will create one frame and attach everything to it *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) ); // Get the properties of the frame frame_properties = MLT_FRAME_PROPERTIES( *frame ); // Loop through each of the tracks we're harvesting for ( i = 0; !done; i ++ ) { // Get a frame from the producer mlt_service_get_frame( self->producer, &temp, i ); // Get the temporary properties temp_properties = MLT_FRAME_PROPERTIES( temp ); // Pass all unique meta properties from the producer's frame to the new frame mlt_properties_lock( temp_properties ); int props_count = mlt_properties_count( temp_properties ); int j; for ( j = 0; j < props_count; j ++ ) { char *name = mlt_properties_get_name( temp_properties, j ); if ( !strncmp( name, "meta.", 5 ) && !mlt_properties_get( frame_properties, name ) ) mlt_properties_set( frame_properties, name, mlt_properties_get_value( temp_properties, j ) ); } mlt_properties_unlock( temp_properties ); // Copy the format conversion virtual functions if ( ! (*frame)->convert_image && temp->convert_image ) (*frame)->convert_image = temp->convert_image; if ( ! (*frame)->convert_audio && temp->convert_audio ) (*frame)->convert_audio = temp->convert_audio; // Check for last track done = mlt_properties_get_int( temp_properties, "last_track" ); // Handle fx only tracks if ( mlt_properties_get_int( temp_properties, "fx_cut" ) ) { int hide = ( video == NULL ? 1 : 0 ) | ( audio == NULL ? 2 : 0 ); mlt_properties_set_int( temp_properties, "hide", hide ); } // We store all frames with a destructor on the output frame sprintf( label, "_%s_%d", id, count ++ ); mlt_properties_set_data( frame_properties, label, temp, 0, ( mlt_destructor )mlt_frame_close, NULL ); // We want to append all 'final' feeds to the global queue if ( !done && mlt_properties_get_data( temp_properties, "data_queue", NULL ) != NULL ) { // Move the contents of this queue on to the output frames data queue mlt_deque sub_queue = mlt_properties_get_data( MLT_FRAME_PROPERTIES( temp ), "data_queue", NULL ); mlt_deque temp = mlt_deque_init( ); while ( global_feed && mlt_deque_count( sub_queue ) ) { mlt_properties p = mlt_deque_pop_back( sub_queue ); if ( mlt_properties_get_int( p, "final" ) ) mlt_deque_push_back( data_queue, p ); else mlt_deque_push_back( temp, p ); } while( mlt_deque_count( temp ) ) mlt_deque_push_front( sub_queue, mlt_deque_pop_back( temp ) ); mlt_deque_close( temp ); } // Now do the same with the global queue but without the conditional behaviour if ( mlt_properties_get_data( temp_properties, "global_queue", NULL ) != NULL ) { mlt_deque sub_queue = mlt_properties_get_data( MLT_FRAME_PROPERTIES( temp ), "global_queue", NULL ); while ( mlt_deque_count( sub_queue ) ) { mlt_properties p = mlt_deque_pop_back( sub_queue ); mlt_deque_push_back( data_queue, p ); } } // Pick up first video and audio frames if ( !done && !mlt_frame_is_test_audio( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 2 ) ) { // Order of frame creation is starting to get problematic if ( audio != NULL ) { mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), producer_get_audio ); mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), audio ); } audio = temp; } if ( !done && !mlt_frame_is_test_card( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 1 ) ) { if ( video != NULL ) { mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), producer_get_image ); mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), video ); } video = temp; if ( first_video == NULL ) first_video = temp; mlt_properties_set_int( MLT_FRAME_PROPERTIES( temp ), "image_count", ++ image_count ); image_count = 1; } } // Now stack callbacks if ( audio != NULL ) { mlt_frame_push_audio( *frame, audio ); mlt_frame_push_audio( *frame, producer_get_audio ); } if ( video != NULL ) { mlt_properties video_properties = MLT_FRAME_PROPERTIES( first_video ); mlt_frame_push_service( *frame, video ); mlt_frame_push_service( *frame, producer_get_image ); if ( global_feed ) mlt_properties_set_data( frame_properties, "data_queue", data_queue, 0, NULL, NULL ); mlt_properties_set_data( video_properties, "global_queue", data_queue, 0, destroy_data_queue, NULL ); mlt_properties_set_int( frame_properties, "width", mlt_properties_get_int( video_properties, "width" ) ); mlt_properties_set_int( frame_properties, "height", mlt_properties_get_int( video_properties, "height" ) ); mlt_properties_pass_list( frame_properties, video_properties, "meta.media.width, meta.media.height" ); mlt_properties_set_int( frame_properties, "progressive", mlt_properties_get_int( video_properties, "progressive" ) ); mlt_properties_set_double( frame_properties, "aspect_ratio", mlt_properties_get_double( video_properties, "aspect_ratio" ) ); mlt_properties_set_int( frame_properties, "image_count", image_count ); mlt_properties_set_data( frame_properties, "_producer", mlt_frame_get_original_producer( first_video ), 0, NULL, NULL ); } else { destroy_data_queue( data_queue ); } mlt_frame_set_position( *frame, mlt_producer_frame( parent ) ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_audio", audio == NULL ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", video == NULL ); } else if ( producer != NULL ) { mlt_producer_seek( producer, mlt_producer_frame( parent ) ); mlt_producer_set_speed( producer, mlt_producer_get_speed( parent ) ); mlt_service_get_frame( self->producer, frame, track ); } else { mlt_log( MLT_PRODUCER_SERVICE( parent ), MLT_LOG_ERROR, "tractor without a multitrack!!\n" ); mlt_service_get_frame( self->producer, frame, track ); } // Prepare the next frame mlt_producer_prepare_next( parent ); // Indicate our found status return 0; } else { // Generate a test card *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) ); return 0; } }
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_filter) mlt_frame_pop_service( frame ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_position pos = mlt_filter_get_position( filter, frame ); mlt_position len = mlt_filter_get_length2( filter, frame ); int maxdia = mlt_properties_anim_get_int( properties, "maxdiameter", pos, len ); int maxcount = mlt_properties_anim_get_int( properties, "maxcount", pos, len ); *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Load svg char *factory = mlt_properties_get( properties, "factory" ); char temp[1204] = ""; sprintf( temp, "%s/oldfilm/", mlt_environment( "MLT_DATA" ) ); mlt_properties direntries = mlt_properties_new(); mlt_properties_dir_list( direntries, temp,"dust*.svg",1 ); if (!maxcount) return 0; double position = mlt_filter_get_progress( filter, frame ); srand( position * 10000 ); mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); int im = rand() % maxcount; int piccount = mlt_properties_count( direntries ); while ( im-- && piccount ) { int picnum = rand() % piccount; int y1 = rand() % *height; int x1 = rand() % *width; char resource[1024] = ""; char savename[1024] = "", savename1[1024] = "", cachedy[100]; int dx = ( *width * maxdia / 100); int luma_width, luma_height; uint8_t *luma_image = NULL; uint8_t *alpha = NULL; int updown = rand() % 2; int mirror = rand() % 2; sprintf( resource, "%s", mlt_properties_get_value(direntries,picnum) ); sprintf( savename, "cache-%d-%d", picnum,dx ); sprintf( savename1, "cache-alpha-%d-%d", picnum, dx ); sprintf( cachedy, "cache-dy-%d-%d", picnum,dx ); luma_image = mlt_properties_get_data( properties , savename , NULL ); alpha = mlt_properties_get_data( properties , savename1 , NULL ); if ( luma_image == NULL || alpha == NULL ) { mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) ); mlt_producer producer = mlt_factory_producer( profile, factory, resource ); if ( producer != NULL ) { mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_properties_set( producer_properties, "eof", "loop" ); mlt_frame luma_frame = NULL; if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &luma_frame, 0 ) == 0 ) { mlt_image_format luma_format = mlt_image_yuv422; luma_width = dx; luma_height = luma_width * mlt_properties_get_int( MLT_FRAME_PROPERTIES ( luma_frame ) , "height" ) / mlt_properties_get_int( MLT_FRAME_PROPERTIES ( luma_frame ) , "width" ); mlt_properties_set( MLT_FRAME_PROPERTIES( luma_frame ), "rescale.interp", "best" );// none/nearest/tiles/hyper mlt_frame_get_image( luma_frame, &luma_image, &luma_format, &luma_width, &luma_height, 0 ); alpha = mlt_frame_get_alpha_mask (luma_frame ); uint8_t* savealpha = mlt_pool_alloc( luma_width * luma_height ); uint8_t* savepic = mlt_pool_alloc( luma_width * luma_height * 2); if ( savealpha && savepic ) { memcpy( savealpha, alpha , luma_width * luma_height ); memcpy( savepic, luma_image , luma_width * luma_height * 2 ); mlt_properties_set_data( properties, savename, savepic, luma_width * luma_height * 2, mlt_pool_release, NULL ); mlt_properties_set_data( properties, savename1, savealpha, luma_width * luma_height, mlt_pool_release, NULL ); mlt_properties_set_int( properties, cachedy, luma_height ); overlay_image( *image, *width, *height, luma_image, luma_width, luma_height, alpha, x1, y1, updown, mirror ); } else { if ( savealpha ) mlt_pool_release( savealpha ); if ( savepic ) mlt_pool_release( savepic ); } mlt_frame_close( luma_frame ); } mlt_producer_close( producer ); } } else { overlay_image ( *image, *width, *height, luma_image, dx, mlt_properties_get_int ( properties, cachedy ), alpha, x1, y1, updown, mirror ); } } mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); if (piccount>0 ) return 0; if ( error == 0 && *image ) { int h = *height; int w = *width; int im = rand() % maxcount; while ( im-- ) { int type = im % 2; int y1 = rand() % h; int x1 = rand() % w; int dx = rand() % maxdia; int dy = rand() % maxdia; int x=0, y=0; double v = 0.0; for ( x = -dx ; x < dx ; x++ ) { for ( y = -dy ; y < dy ; y++ ) { if ( x1 + x < w && x1 + x > 0 && y1 + y < h && y1 + y > 0 ){ uint8_t *pix = *image + (y+y1) * w * 2 + (x + x1) * 2; v=pow((double) x /(double)dx * 5.0, 2.0) + pow((double)y / (double)dy * 5.0, 2.0); if (v>10) v=10; v = 1.0 - ( v / 10.0 ); switch(type) { case 0: *pix -= (*pix) * v; break; case 1: *pix += ( 255-*pix ) * v; break; } } } } } } return error; }
static void add_parameters( mlt_properties params, void *object, int req_flags, const char *unit, const char *subclass ) { const AVOption *opt = NULL; // For each AVOption on the AVClass object #if LIBAVUTIL_VERSION_INT >= ((51<<16)+(12<<8)+0) while ( ( opt = av_opt_next( object, opt ) ) ) #else while ( ( opt = av_next_option( object, opt ) ) ) #endif { // If matches flags and not a binary option (not supported by Mlt) if ( !( opt->flags & req_flags ) || ( opt->type == AV_OPT_TYPE_BINARY ) ) continue; // Ignore constants (keyword values) if ( !unit && opt->type == AV_OPT_TYPE_CONST ) continue; // When processing a groups of options (unit)... // ...ignore non-constants else if ( unit && opt->type != AV_OPT_TYPE_CONST ) continue; // ...ignore constants not in this group else if ( unit && opt->type == AV_OPT_TYPE_CONST && strcmp( unit, opt->unit ) ) continue; // ..add constants to the 'values' sequence else if ( unit && opt->type == AV_OPT_TYPE_CONST ) { char key[20]; snprintf( key, 20, "%d", mlt_properties_count( params ) ); mlt_properties_set( params, key, opt->name ); continue; } // Create a map for this option. mlt_properties p = mlt_properties_new(); char key[20]; snprintf( key, 20, "%d", mlt_properties_count( params ) ); // Add the map to the 'parameters' sequence. mlt_properties_set_data( params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL ); // Add the parameter metadata for this AVOption. mlt_properties_set( p, "identifier", opt->name ); if ( opt->help ) { if ( subclass ) { char *s = malloc( strlen( opt->help ) + strlen( subclass ) + 4 ); strcpy( s, opt->help ); strcat( s, " (" ); strcat( s, subclass ); strcat( s, ")" ); mlt_properties_set( p, "description", s ); free( s ); } else mlt_properties_set( p, "description", opt->help ); } switch ( opt->type ) { case AV_OPT_TYPE_FLAGS: mlt_properties_set( p, "type", "string" ); mlt_properties_set( p, "format", "flags" ); break; case AV_OPT_TYPE_INT: if ( !opt->unit ) { mlt_properties_set( p, "type", "integer" ); if ( opt->min != INT_MIN ) mlt_properties_set_int( p, "minimum", (int) opt->min ); if ( opt->max != INT_MAX ) mlt_properties_set_int( p, "maximum", (int) opt->max ); #if LIBAVUTIL_VERSION_MAJOR > 50 mlt_properties_set_int( p, "default", (int) opt->default_val.dbl ); #endif } else { mlt_properties_set( p, "type", "string" ); mlt_properties_set( p, "format", "integer or keyword" ); } break; case AV_OPT_TYPE_INT64: mlt_properties_set( p, "type", "integer" ); mlt_properties_set( p, "format", "64-bit" ); if ( opt->min != INT64_MIN ) mlt_properties_set_int64( p, "minimum", (int64_t) opt->min ); if ( opt->max != INT64_MAX ) mlt_properties_set_int64( p, "maximum", (int64_t) opt->max ); #if LIBAVUTIL_VERSION_MAJOR > 50 mlt_properties_set_int64( p, "default", (int64_t) opt->default_val.dbl ); #endif break; case AV_OPT_TYPE_FLOAT: mlt_properties_set( p, "type", "float" ); if ( opt->min != FLT_MIN && opt->min != -340282346638528859811704183484516925440.0 ) mlt_properties_set_double( p, "minimum", opt->min ); if ( opt->max != FLT_MAX ) mlt_properties_set_double( p, "maximum", opt->max ); #if LIBAVUTIL_VERSION_MAJOR > 50 mlt_properties_set_double( p, "default", opt->default_val.dbl ); #endif break; case AV_OPT_TYPE_DOUBLE: mlt_properties_set( p, "type", "float" ); mlt_properties_set( p, "format", "double" ); if ( opt->min != DBL_MIN ) mlt_properties_set_double( p, "minimum", opt->min ); if ( opt->max != DBL_MAX ) mlt_properties_set_double( p, "maximum", opt->max ); #if LIBAVUTIL_VERSION_MAJOR > 50 mlt_properties_set_double( p, "default", opt->default_val.dbl ); #endif break; case AV_OPT_TYPE_STRING: mlt_properties_set( p, "type", "string" ); #if LIBAVUTIL_VERSION_MAJOR > 50 mlt_properties_set( p, "default", opt->default_val.str ); #endif break; case AV_OPT_TYPE_RATIONAL: mlt_properties_set( p, "type", "string" ); mlt_properties_set( p, "format", "numerator:denominator" ); break; case AV_OPT_TYPE_CONST: default: mlt_properties_set( p, "type", "integer" ); mlt_properties_set( p, "format", "constant" ); break; } // If the option belongs to a group (unit) and is not a constant (keyword value) if ( opt->unit && opt->type != AV_OPT_TYPE_CONST ) { // Create a 'values' sequence. mlt_properties values = mlt_properties_new(); // Recurse to add constants in this group to the 'values' sequence. add_parameters( values, object, req_flags, opt->unit, NULL ); if ( mlt_properties_count( values ) ) mlt_properties_set_data( p, "values", values, 0, (mlt_destructor) mlt_properties_close, NULL ); else mlt_properties_close( values ); } } }
static mlt_properties metadata( mlt_service_type type, const char *id, char *data ) { char file[ PATH_MAX ]; if( type == filter_type ) { snprintf( file, PATH_MAX, "%s/jackrack/%s", mlt_environment( "MLT_DATA" ), strncmp( id, "ladspa.", 7 ) ? data : "filter_ladspa.yml" ); } else { snprintf( file, PATH_MAX, "%s/jackrack/%s", mlt_environment( "MLT_DATA" ), strncmp( id, "ladspa.", 7 ) ? data : "producer_ladspa.yml" ); } mlt_properties result = mlt_properties_parse_yaml( file ); #ifdef GPL if ( !strncmp( id, "ladspa.", 7 ) ) { // Annotate the yaml properties with ladspa control port info. plugin_desc_t *desc = plugin_mgr_get_any_desc( g_jackrack_plugin_mgr, strtol( id + 7, NULL, 10 ) ); if ( desc ) { mlt_properties params = mlt_properties_new(); mlt_properties p; char key[20]; int i; mlt_properties_set( result, "identifier", id ); mlt_properties_set( result, "title", desc->name ); mlt_properties_set( result, "creator", desc->maker ? desc->maker : "unknown" ); mlt_properties_set( result, "description", "LADSPA plugin" ); mlt_properties_set_data( result, "parameters", params, 0, (mlt_destructor) mlt_properties_close, NULL ); for ( i = 0; i < desc->control_port_count; i++ ) { int j = desc->control_port_indicies[i]; p = mlt_properties_new(); snprintf( key, sizeof(key), "%d", mlt_properties_count( params ) ); mlt_properties_set_data( params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL ); snprintf( key, sizeof(key), "%d", j ); mlt_properties_set( p, "identifier", key ); add_port_to_metadata( p, desc, j ); mlt_properties_set( p, "mutable", "yes" ); } for ( i = 0; i < desc->status_port_count; i++ ) { int j = desc->status_port_indicies[i]; p = mlt_properties_new(); snprintf( key, sizeof(key), "%d", mlt_properties_count( params ) ); mlt_properties_set_data( params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL ); snprintf( key, sizeof(key), "%d[*]", j ); mlt_properties_set( p, "identifier", key ); add_port_to_metadata( p, desc, j ); mlt_properties_set( p, "readonly", "yes" ); } p = mlt_properties_new(); snprintf( key, sizeof(key), "%d", mlt_properties_count( params ) ); mlt_properties_set_data( params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL ); mlt_properties_set( p, "identifier", "instances" ); mlt_properties_set( p, "title", "Instances" ); mlt_properties_set( p, "description", "The number of instances of the plugin that are in use.\n" "MLT will create the number of plugins that are required " "to support the number of audio channels.\n" "Status parameters (readonly) are provided for each instance " "and are accessed by specifying the instance number after the " "identifier (starting at zero).\n" "e.g. 9[0] provides the value of status 9 for the first instance." ); mlt_properties_set( p, "type", "integer" ); mlt_properties_set( p, "readonly", "yes" ); if( type == filter_type ) { p = mlt_properties_new(); snprintf( key, sizeof(key), "%d", mlt_properties_count( params ) ); mlt_properties_set_data( params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL ); mlt_properties_set( p, "identifier", "wetness" ); mlt_properties_set( p, "title", "Wet/Dry" ); mlt_properties_set( p, "type", "float" ); mlt_properties_set_double( p, "default", 1 ); mlt_properties_set_double( p, "minimum", 0 ); mlt_properties_set_double( p, "maximum", 1 ); mlt_properties_set( p, "mutable", "yes" ); } } } #endif return result; }