int mlt_consumer_init( mlt_consumer self, void *child, mlt_profile profile ) { int error = 0; memset( self, 0, sizeof( struct mlt_consumer_s ) ); self->child = child; error = mlt_service_init( &self->parent, self ); if ( error == 0 ) { // Get the properties from the service mlt_properties properties = MLT_SERVICE_PROPERTIES( &self->parent ); // Apply profile to properties if ( profile == NULL ) { // Normally the application creates the profile and controls its lifetime // This is the fallback exception handling profile = mlt_profile_init( NULL ); mlt_properties properties = MLT_CONSUMER_PROPERTIES( self ); mlt_properties_set_data( properties, "_profile", profile, 0, (mlt_destructor)mlt_profile_close, NULL ); } apply_profile_properties( self, profile, properties ); // Default rescaler for all consumers mlt_properties_set( properties, "rescale", "bilinear" ); // Default read ahead buffer size mlt_properties_set_int( properties, "buffer", 25 ); mlt_properties_set_int( properties, "drop_max", 5 ); // Default audio frequency and channels mlt_properties_set_int( properties, "frequency", 48000 ); mlt_properties_set_int( properties, "channels", 2 ); // Default of all consumers is real time mlt_properties_set_int( properties, "real_time", 1 ); // Default to environment test card mlt_properties_set( properties, "test_card", mlt_environment( "MLT_TEST_CARD" ) ); // Hmm - default all consumers to yuv422 :-/ self->format = mlt_image_yuv422; mlt_properties_set( properties, "mlt_image_format", mlt_image_format_name( self->format ) ); mlt_properties_set( properties, "mlt_audio_format", mlt_audio_format_name( mlt_audio_s16 ) ); mlt_events_register( properties, "consumer-frame-show", ( mlt_transmitter )mlt_consumer_frame_show ); mlt_events_register( properties, "consumer-frame-render", ( mlt_transmitter )mlt_consumer_frame_render ); mlt_events_register( properties, "consumer-stopped", NULL ); mlt_events_listen( properties, self, "consumer-frame-show", ( mlt_listener )on_consumer_frame_show ); // Register a property-changed listener to handle the profile property - // subsequent properties can override the profile self->event_listener = mlt_events_listen( properties, self, "property-changed", ( mlt_listener )mlt_consumer_property_changed ); // Create the push mutex and condition pthread_mutex_init( &self->put_mutex, NULL ); pthread_cond_init( &self->put_cond, NULL ); } return error; }
int mlt_service_init( mlt_service self, void *child ) { int error = 0; // Initialise everything to NULL memset( self, 0, sizeof( struct mlt_service_s ) ); // Assign the child self->child = child; // Generate local space self->local = calloc( 1, sizeof( mlt_service_base ) ); // Associate the methods self->get_frame = service_get_frame; // Initialise the properties error = mlt_properties_init( &self->parent, self ); if ( error == 0 ) { self->parent.close = ( mlt_destructor )mlt_service_close; self->parent.close_object = self; mlt_events_init( &self->parent ); mlt_events_register( &self->parent, "service-changed", NULL ); mlt_events_register( &self->parent, "property-changed", ( mlt_transmitter )mlt_service_property_changed ); pthread_mutex_init( &( ( mlt_service_base * )self->local )->mutex, NULL ); } return error; }
int mlt_producer_init( mlt_producer self, void *child ) { // Check that we haven't received NULL int error = self == NULL; // Continue if no error if ( error == 0 ) { #ifdef _MLT_PRODUCER_CHECKS_ producers_created ++; #endif // Initialise the producer memset( self, 0, sizeof( struct mlt_producer_s ) ); // Associate with the child self->child = child; // Initialise the service if ( mlt_service_init( &self->parent, self ) == 0 ) { // The parent is the service mlt_service parent = &self->parent; // Define the parent close parent->close = ( mlt_destructor )mlt_producer_close; parent->close_object = self; // For convenience, we'll assume the close_object is self self->close_object = self; // Get the properties of the parent mlt_properties properties = MLT_SERVICE_PROPERTIES( parent ); // Set the default properties mlt_properties_set( properties, "mlt_type", "mlt_producer" ); mlt_properties_set_position( properties, "_position", 0.0 ); mlt_properties_set_double( properties, "_frame", 0 ); mlt_properties_set_double( properties, "_speed", 1.0 ); mlt_properties_set_position( properties, "in", 0 ); char *e = getenv( "MLT_DEFAULT_PRODUCER_LENGTH" ); int p = e ? atoi( e ) : 15000; mlt_properties_set_position( properties, "out", p - 1 ); mlt_properties_set_position( properties, "length", p ); mlt_properties_set( properties, "eof", "pause" ); mlt_properties_set( properties, "resource", "<producer>" ); // Override service get_frame parent->get_frame = producer_get_frame; mlt_events_listen( properties, self, "service-changed", ( mlt_listener )mlt_producer_service_changed ); mlt_events_listen( properties, self, "property-changed", ( mlt_listener )mlt_producer_property_changed ); mlt_events_register( properties, "producer-changed", NULL ); } } return error; }
GlslManager::GlslManager() : Mlt::Filter( mlt_filter_new() ) , pbo(0) , initEvent(0) , closeEvent(0) { mlt_filter filter = get_filter(); if ( filter ) { // Set the mlt_filter child in case we choose to override virtual functions. filter->child = this; mlt_properties_set_data(mlt_global_properties(), "glslManager", this, 0, (mlt_destructor) deleteManager, NULL); mlt_events_register( get_properties(), "init glsl", NULL ); mlt_events_register( get_properties(), "close glsl", NULL ); initEvent = listen("init glsl", this, (mlt_listener) GlslManager::onInit); closeEvent = listen("close glsl", this, (mlt_listener) GlslManager::onClose); } }
mlt_consumer consumer_sdl_preview_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { consumer_sdl self = calloc( 1, sizeof( struct consumer_sdl_s ) ); if ( self != NULL && mlt_consumer_init( &self->parent, self, profile ) == 0 ) { // Get the parent consumer object mlt_consumer parent = &self->parent; // Get the properties mlt_properties properties = MLT_CONSUMER_PROPERTIES( parent ); // Get the width and height int width = mlt_properties_get_int( properties, "width" ); int height = mlt_properties_get_int( properties, "height" ); // Process actual param if ( arg == NULL || sscanf( arg, "%dx%d", &width, &height ) == 2 ) { mlt_properties_set_int( properties, "width", width ); mlt_properties_set_int( properties, "height", height ); } // Create child consumers self->play = mlt_factory_consumer( profile, "sdl", arg ); self->still = mlt_factory_consumer( profile, "sdl_still", arg ); mlt_properties_set( properties, "rescale", "nearest" ); mlt_properties_set( properties, "deinterlace_method", "onefield" ); mlt_properties_set_int( properties, "prefill", 1 ); mlt_properties_set_int( properties, "top_field_first", -1 ); parent->close = consumer_close; parent->start = consumer_start; parent->stop = consumer_stop; parent->is_stopped = consumer_is_stopped; parent->purge = consumer_purge; self->joined = 1; mlt_events_listen( MLT_CONSUMER_PROPERTIES( self->play ), self, "consumer-frame-show", ( mlt_listener )consumer_frame_show_cb ); mlt_events_listen( MLT_CONSUMER_PROPERTIES( self->still ), self, "consumer-frame-show", ( mlt_listener )consumer_frame_show_cb ); mlt_events_listen( MLT_CONSUMER_PROPERTIES( self->play ), self, "consumer-sdl-event", ( mlt_listener )consumer_sdl_event_cb ); mlt_events_listen( MLT_CONSUMER_PROPERTIES( self->still ), self, "consumer-sdl-event", ( mlt_listener )consumer_sdl_event_cb ); pthread_cond_init( &self->refresh_cond, NULL ); pthread_mutex_init( &self->refresh_mutex, NULL ); mlt_events_listen( MLT_CONSUMER_PROPERTIES( parent ), self, "property-changed", ( mlt_listener )consumer_refresh_cb ); mlt_events_register( properties, "consumer-sdl-paused", NULL ); return parent; } free( self ); return NULL; }
/** This is what will be called by the factory * @param profile: profile name for consumer * @param type: unused * @param *id: unused * @param *arg: pointer to output path **/ mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg) { // Create the consumer object consumer_SDIstream this = calloc( 1, sizeof(struct consumer_SDIstream_s) ); // If malloc and consumer init ok if (this != NULL && mlt_consumer_init(&this->parent, this, profile) == 0) { // Get the parent consumer object mlt_consumer parent = &this->parent; // We have stuff to clean up, so override the close method parent->close = consumer_close; // Set output path for SDI, default is "/dev/sditx0" if (arg == NULL) { this->device_file_video = strdup("/dev/sditx0"); } else { this->device_file_video = strdup(arg); } // Set up start/stop/terminated callbacks parent->start = consumer_start; parent->stop = consumer_stop; parent->is_stopped = consumer_is_stopped; // Set explicit to zero or other value int i, j; for (i = 0; i < MAX_AUDIO_STREAMS; i++) { for (j = 0; j < MAX_AUDIO_SAMPLES; j++) { this->audio_buffer[i][j] = j; } } mlt_events_register( MLT_CONSUMER_PROPERTIES(parent), "consumer-fatal-error", NULL ); // Return the consumer produced return parent; } // malloc or consumer init failed free(this); // Indicate failure return NULL; }
mlt_consumer consumer_sdl2_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { // Create the consumer object consumer_sdl self = calloc( 1, sizeof( struct consumer_sdl_s ) ); // If no malloc'd and consumer init ok if ( self != NULL && mlt_consumer_init( &self->parent, self, profile ) == 0 ) { // Create the queue self->queue = mlt_deque_init( ); // Get the parent consumer object mlt_consumer parent = &self->parent; // We have stuff to clean up, so override the close method parent->close = consumer_close; // get a handle on properties mlt_service service = MLT_CONSUMER_SERVICE( parent ); self->properties = MLT_SERVICE_PROPERTIES( service ); // Set the default volume mlt_properties_set_double( self->properties, "volume", 1.0 ); // This is the initialisation of the consumer pthread_mutex_init( &self->audio_mutex, NULL ); pthread_cond_init( &self->audio_cond, NULL); pthread_mutex_init( &self->video_mutex, NULL ); pthread_cond_init( &self->video_cond, NULL); // Default scaler (for now we'll use nearest) mlt_properties_set( self->properties, "rescale", "nearest" ); mlt_properties_set( self->properties, "deinterlace_method", "onefield" ); mlt_properties_set_int( self->properties, "top_field_first", -1 ); // Default buffer for low latency mlt_properties_set_int( self->properties, "buffer", 1 ); // Default audio buffer mlt_properties_set_int( self->properties, "audio_buffer", 2048 ); #if defined(_WIN32) && SDL_MAJOR_VERSION == 2 mlt_properties_set( self->properties, "audio_driver", "DirectSound" ); #endif // Ensure we don't join on a non-running object self->joined = 1; // process actual param if ( arg && sscanf( arg, "%dx%d", &self->width, &self->height ) ) { mlt_properties_set_int( self->properties, "resolution", 1 ); } else { self->width = mlt_properties_get_int( self->properties, "width" ); self->height = mlt_properties_get_int( self->properties, "height" ); } // Allow thread to be started/stopped parent->start = consumer_start; parent->stop = consumer_stop; parent->is_stopped = consumer_is_stopped; parent->purge = consumer_purge; // Register specific events mlt_events_register( self->properties, "consumer-sdl-event", ( mlt_transmitter )consumer_sdl_event ); // Return the consumer produced return parent; } // malloc or consumer init failed free( self ); // Indicate failure return NULL; }
mlt_producer producer_pango_init( const char *filename ) { producer_pango this = calloc( 1, sizeof( struct producer_pango_s ) ); 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 ); mlt_events_register( properties, "fontmap-reload", NULL ); mlt_events_listen( properties, producer, "fontmap-reload", (mlt_listener) on_fontmap_reload ); // 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, "stretch", PANGO_STRETCH_NORMAL + 1 ); mlt_properties_set_int( properties, "rotate", 0 ); mlt_properties_set_int( properties, "seekable", 1 ); if ( filename == NULL || ( filename && ( !strcmp( filename, "" ) || strstr( filename, "<producer>" ) // 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; if ( strrchr( markup, '.' ) ) ( *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_position out_point = 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 ); out_point = MAX( out_point, item.frame ); } mlt_geometry_interpolate( key_frames ); mlt_properties_set_position( properties, "length", out_point + 1 ); mlt_properties_set_position( properties, "out", out_point ); } else { // Convert file name string encoding. mlt_properties_set( properties, "resource", filename ); mlt_properties_from_utf8( properties, "resource", "_resource" ); filename = mlt_properties_get( properties, "_resource" ); 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 ); if ( markup ) strcat( markup, line ); } else { markup = strdup( line ); } } fclose( f ); if ( markup && markup[ strlen( markup ) - 1 ] == '\n' ) markup[ strlen( markup ) - 1 ] = '\0'; if ( markup ) mlt_properties_set( properties, "markup", markup ); else mlt_properties_set( properties, "markup", "" ); free( markup ); } else { producer->close = NULL; mlt_producer_close( producer ); producer = NULL; free( this ); } } return producer; } free( this ); return NULL; }
mlt_repository mlt_factory_init( const char *directory ) { // Load the system locales setlocale( LC_ALL, "" ); if ( ! global_properties ) global_properties = mlt_properties_new( ); // Allow property refresh on a subsequent initialisation if ( global_properties ) { mlt_properties_set_or_default( global_properties, "MLT_NORMALISATION", getenv( "MLT_NORMALISATION" ), "PAL" ); mlt_properties_set_or_default( global_properties, "MLT_PRODUCER", getenv( "MLT_PRODUCER" ), "loader" ); mlt_properties_set_or_default( global_properties, "MLT_CONSUMER", getenv( "MLT_CONSUMER" ), "sdl" ); mlt_properties_set( global_properties, "MLT_TEST_CARD", getenv( "MLT_TEST_CARD" ) ); mlt_properties_set_or_default( global_properties, "MLT_PROFILE", getenv( "MLT_PROFILE" ), "dv_pal" ); mlt_properties_set_or_default( global_properties, "MLT_DATA", getenv( "MLT_DATA" ), PREFIX_DATA ); #if defined(WIN32) char path[1024]; DWORD size = sizeof( path ); GetModuleFileName( NULL, path, size ); #elif defined(__DARWIN__) && defined(RELOCATABLE) char path[1024]; uint32_t size = sizeof( path ); _NSGetExecutablePath( path, &size ); #endif #if defined(WIN32) || (defined(__DARWIN__) && defined(RELOCATABLE)) char *path2 = strdup( path ); char *appdir = dirname( path2 ); mlt_properties_set( global_properties, "MLT_APPDIR", appdir ); free( path2 ); #endif } // Only initialise once if ( mlt_directory == NULL ) { #if !defined(WIN32) && !(defined(__DARWIN__) && defined(RELOCATABLE)) // Allow user overrides if ( directory == NULL || !strcmp( directory, "" ) ) directory = getenv( "MLT_REPOSITORY" ); #endif // If no directory is specified, default to install directory if ( directory == NULL ) directory = PREFIX_LIB; // Store the prefix for later retrieval #if defined(WIN32) || (defined(__DARWIN__) && defined(RELOCATABLE)) char *exedir = mlt_environment( "MLT_APPDIR" ); size_t size = strlen( exedir ); if ( global_properties && !getenv( "MLT_DATA" ) ) { mlt_directory = calloc( 1, size + strlen( PREFIX_DATA ) + 1 ); strcpy( mlt_directory, exedir ); strcat( mlt_directory, PREFIX_DATA ); mlt_properties_set( global_properties, "MLT_DATA", mlt_directory ); free( mlt_directory ); } mlt_directory = calloc( 1, size + strlen( directory ) + 1 ); strcpy( mlt_directory, exedir ); strcat( mlt_directory, directory ); #else mlt_directory = strdup( directory ); #endif // Initialise the pool mlt_pool_init( ); // Create and set up the events object event_object = mlt_properties_new( ); mlt_events_init( event_object ); mlt_events_register( event_object, "producer-create-request", ( mlt_transmitter )mlt_factory_create_request ); mlt_events_register( event_object, "producer-create-done", ( mlt_transmitter )mlt_factory_create_done ); mlt_events_register( event_object, "filter-create-request", ( mlt_transmitter )mlt_factory_create_request ); mlt_events_register( event_object, "filter-create-done", ( mlt_transmitter )mlt_factory_create_done ); mlt_events_register( event_object, "transition-create-request", ( mlt_transmitter )mlt_factory_create_request ); mlt_events_register( event_object, "transition-create-done", ( mlt_transmitter )mlt_factory_create_done ); mlt_events_register( event_object, "consumer-create-request", ( mlt_transmitter )mlt_factory_create_request ); mlt_events_register( event_object, "consumer-create-done", ( mlt_transmitter )mlt_factory_create_done ); // Create the repository of services repository = mlt_repository_init( mlt_directory ); // Force a clean up when app closes atexit( mlt_factory_close ); } if ( global_properties ) { char *path = getenv( "MLT_PRESETS_PATH" ); if ( path ) { mlt_properties_set( global_properties, "MLT_PRESETS_PATH", path ); } else { path = malloc( strlen( mlt_environment( "MLT_DATA" ) ) + strlen( PRESETS_DIR ) + 1 ); strcpy( path, mlt_environment( "MLT_DATA" ) ); strcat( path, PRESETS_DIR ); mlt_properties_set( global_properties, "MLT_PRESETS_PATH", path ); free( path ); } } return repository; }