예제 #1
0
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;
}
예제 #2
0
파일: mlt_producer.c 프로젝트: jliljebl/mlt
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;
}
예제 #3
0
파일: melt.c 프로젝트: hrshadhin/mlt
static void setup_jack_transport( mlt_consumer consumer, mlt_profile profile )
{
    mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
    mlt_filter jack = mlt_factory_filter( profile, "jackrack", NULL );
    mlt_properties jack_properties = MLT_FILTER_PROPERTIES(jack);

    mlt_service_attach( MLT_CONSUMER_SERVICE(consumer), jack );
    mlt_properties_set_int( properties, "audio_off", 1 );
    mlt_properties_set_data( properties, "jack_filter", jack, 0, (mlt_destructor) mlt_filter_close, NULL );
//	mlt_properties_set( jack_properties, "out_1", "system:playback_1" );
//	mlt_properties_set( jack_properties, "out_2", "system:playback_2" );
    mlt_events_listen( jack_properties, consumer, "jack-started", (mlt_listener) on_jack_started );
    mlt_events_listen( jack_properties, consumer, "jack-stopped", (mlt_listener) on_jack_stopped );
}
예제 #4
0
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;
}
예제 #5
0
파일: mlt_tractor.c 프로젝트: elfring/mlt
mlt_tractor mlt_tractor_new( )
{
	mlt_tractor self = calloc( 1, sizeof( struct mlt_tractor_s ) );
	if ( self != NULL )
	{
		mlt_producer producer = &self->parent;
		if ( mlt_producer_init( producer, self ) == 0 )
		{
			mlt_multitrack multitrack = mlt_multitrack_init( );
			mlt_field field = mlt_field_new( multitrack, self );
			mlt_properties props = MLT_PRODUCER_PROPERTIES( producer );

			mlt_properties_set( props, "resource", "<tractor>" );
			mlt_properties_set( props, "mlt_type", "mlt_producer" );
			mlt_properties_set( props, "mlt_service", "tractor" );
			mlt_properties_set_position( props, "in", 0 );
			mlt_properties_set_position( props, "out", 0 );
			mlt_properties_set_position( props, "length", 0 );
			mlt_properties_set_data( props, "multitrack", multitrack, 0, ( mlt_destructor )mlt_multitrack_close, NULL );
			mlt_properties_set_data( props, "field", field, 0, ( mlt_destructor )mlt_field_close, NULL );

			mlt_events_listen( MLT_MULTITRACK_PROPERTIES( multitrack ), self, "producer-changed", ( mlt_listener )mlt_tractor_listener );

			producer->get_frame = producer_get_frame;
			producer->close = ( mlt_destructor )mlt_tractor_close;
			producer->close_object = self;
		}
		else
		{
			free( self );
			self = NULL;
		}
	}
	return self;
}
예제 #6
0
파일: mlt_service.c 프로젝트: bmatherly/mlt
int mlt_service_attach( mlt_service self, mlt_filter filter )
{
	int error = self == NULL || filter == NULL;
	if ( error == 0 )
	{
		int i = 0;
		mlt_properties properties = MLT_SERVICE_PROPERTIES( self );
		mlt_service_base *base = self->local;

		for ( i = 0; error == 0 && i < base->filter_count; i ++ )
			if ( base->filters[ i ] == filter )
				error = 1;

		if ( error == 0 )
		{
			if ( base->filter_count == base->filter_size )
			{
				base->filter_size += 10;
				base->filters = realloc( base->filters, base->filter_size * sizeof( mlt_filter ) );
			}

			if ( base->filters != NULL )
			{
				mlt_properties props = MLT_FILTER_PROPERTIES( filter );
				mlt_properties_inc_ref( MLT_FILTER_PROPERTIES( filter ) );
				base->filters[ base->filter_count ++ ] = filter;
				mlt_properties_set_data( props, "service", self, 0, NULL, NULL );
				mlt_events_fire( properties, "service-changed", NULL );
				mlt_events_fire( props, "service-changed", NULL );
				mlt_service cp = mlt_properties_get_data( properties, "_cut_parent", NULL );
				if ( cp )
					mlt_events_fire( MLT_SERVICE_PROPERTIES(cp), "service-changed", NULL );
				mlt_events_listen( props, self, "service-changed", ( mlt_listener )mlt_service_filter_changed );
				mlt_events_listen( props, self, "property-changed", ( mlt_listener )mlt_service_filter_property_changed );
			}
			else
			{
				error = 2;
			}
		}
	}
	return error;
}
예제 #7
0
void ServiceManager::setupConsumerListener(mlt_frame frame)
{
    // If there is a consumer property, listen to the consumer-stopping event to cancel rendering.
    if (!event) {
        mlt_consumer consumer = static_cast<mlt_consumer>(mlt_properties_get_data(MLT_FRAME_PROPERTIES(frame), "consumer", 0));
        if (consumer) {
            event = MLT_CONSUMER_PROPERTIES(consumer);
            mlt_events_listen(event, this, "consumer-stopping",
                reinterpret_cast<mlt_listener>(MLTWebVfx::consumerStoppingListener));
        }
    }
}
예제 #8
0
파일: mlt_multitrack.c 프로젝트: vpinon/mlt
int mlt_multitrack_insert( mlt_multitrack self, mlt_producer producer, int track )
{
	if ( track >= self->count )
		return mlt_multitrack_connect( self, producer, track );

	// Connect to the producer to ourselves at the specified track
	int result = mlt_service_insert_producer( MLT_MULTITRACK_SERVICE( self ), MLT_PRODUCER_SERVICE( producer ), track );

	if ( result == 0 )
	{
		// Resize the producer list if needed.
		if ( self->count + 1 > self->size )
		{
			int new_size = self->size + 10;
			self->list = realloc( self->list, new_size * sizeof( mlt_track ) );
			if ( self->list )
			{
				memset( &self->list[ self->size ], 0, new_size - self->size );
				self->size = new_size;
			}
		}

		if ( self->list )
		{
			// Move all of the list elements following track N down by 1.
			memmove( &self->list[ track + 1 ], &self->list[ track ],
					( self->count - track ) * sizeof ( mlt_track ) );
			self->count ++;

			// Assign the track in our list.
			self->list[ track ] = malloc( sizeof( struct mlt_track_s ) );
			self->list[ track ]->producer = producer;
			self->list[ track ]->event = mlt_events_listen( MLT_PRODUCER_PROPERTIES( producer ), self,
										 "producer-changed", ( mlt_listener )mlt_multitrack_listener );
			mlt_properties_inc_ref( MLT_PRODUCER_PROPERTIES( producer ) );
			mlt_event_inc_ref( self->list[ track ]->event );

			// TODO: Move this into producer_avformat.c when mlt_events broadcasting is available.
			if ( self->count > mlt_service_cache_get_size( MLT_MULTITRACK_SERVICE( self ), "producer_avformat" ) )
				mlt_service_cache_set_size( MLT_MULTITRACK_SERVICE( self ), "producer_avformat", self->count + 1 );

			// Refresh our stats
			mlt_multitrack_refresh( self );
		}
		else
		{
			result = -1;
		}
	}

	return result;
}
예제 #9
0
파일: mlt_multitrack.c 프로젝트: vpinon/mlt
int mlt_multitrack_connect( mlt_multitrack self, mlt_producer producer, int track )
{
	// Connect to the producer to ourselves at the specified track
	int result = mlt_service_connect_producer( MLT_MULTITRACK_SERVICE( self ), MLT_PRODUCER_SERVICE( producer ), track );

	if ( result == 0 )
	{
		mlt_track current_track = ( track < self->count )? self->list[ track ] : NULL;
		// Resize the producer list if need be
		if ( track >= self->size )
		{
			int i;
			self->list = realloc( self->list, ( track + 10 ) * sizeof( mlt_track ) );
			for ( i = self->size; i < track + 10; i ++ )
				self->list[ i ] = NULL;
			self->size = track + 10;
		}

		if ( current_track )
		{
			mlt_event_close( current_track->event );
			mlt_producer_close( current_track->producer );
		}
		else
		{
			self->list[ track ] = malloc( sizeof( struct mlt_track_s ) );
		}

		// Assign the track in our list here
		self->list[ track ]->producer = producer;
		self->list[ track ]->event = mlt_events_listen( MLT_PRODUCER_PROPERTIES( producer ), self,
									 "producer-changed", ( mlt_listener )mlt_multitrack_listener );
		mlt_properties_inc_ref( MLT_PRODUCER_PROPERTIES( producer ) );
		mlt_event_inc_ref( self->list[ track ]->event );

		// Increment the track count if need be
		if ( track >= self->count )
		{
			self->count = track + 1;

			// TODO: Move this into producer_avformat.c when mlt_events broadcasting is available.
			if ( self->count > mlt_service_cache_get_size( MLT_MULTITRACK_SERVICE( self ), "producer_avformat" ) )
				mlt_service_cache_set_size( MLT_MULTITRACK_SERVICE( self ), "producer_avformat", self->count + 1 );
		}

		// Refresh our stats
		mlt_multitrack_refresh( self );
	}

	return result;
}
예제 #10
0
mlt_filter filter_loudness_meter_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
{
	mlt_filter filter = mlt_filter_new( );
	private_data* pdata = (private_data*)calloc( 1, sizeof(private_data) );

	if( filter && pdata )
	{
		mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
		mlt_properties_set_int( properties, "calc_program", 1 );
		mlt_properties_set_int( properties, "calc_shortterm", 1 );
		mlt_properties_set_int( properties, "calc_momentary", 1 );
		mlt_properties_set_int( properties, "calc_range", 1 );
		mlt_properties_set_int( properties, "calc_peak", 1 );
		mlt_properties_set_int( properties, "calc_true_peak", 1 );
		mlt_properties_set( properties, "program", "-100.0" );
		mlt_properties_set( properties, "shortterm", "-100.0" );
		mlt_properties_set( properties, "momentary", "-100.0" );
		mlt_properties_set( properties, "range", "-1.0" );
		mlt_properties_set( properties, "peak", "-100.0" );
		mlt_properties_set( properties, "max_peak", "-100.0" );
		mlt_properties_set( properties, "true_peak", "-100.0" );
		mlt_properties_set( properties, "max_true_peak", "-100.0" );
		mlt_properties_set( properties, "reset", "1" );
		mlt_properties_set( properties, "reset_count", "0" );
		mlt_properties_set( properties, "frames_processed", "0" );

		pdata->r128 = 0;
		pdata->reset = 1;
		pdata->prev_pos = -1;

		filter->close = filter_close;
		filter->process = filter_process;
		filter->child = pdata;

		mlt_events_listen( properties, filter, "property-changed", (mlt_listener)property_changed );
	}
	else
	{
		if( filter )
		{
			mlt_filter_close( filter );
			filter = NULL;
		}

		free( pdata );
	}

	return filter;
}
예제 #11
0
mlt_filter filter_dynamic_loudness_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
{
	mlt_filter filter = mlt_filter_new( );
	private_data* pdata = (private_data*)calloc( 1, sizeof(private_data) );

	if( filter && pdata )
	{
		mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
		mlt_properties_set( properties, "target_loudness", "-23.0" );
		mlt_properties_set( properties, "window", "3.0" );
		mlt_properties_set( properties, "max_gain", "15.0" );
		mlt_properties_set( properties, "min_gain", "-15.0" );
		mlt_properties_set( properties, "max_rate", "3.0" );
		mlt_properties_set( properties, "in_loudness", "-100.0" );
		mlt_properties_set( properties, "out_gain", "0.0" );
		mlt_properties_set( properties, "reset_count", "0" );

		pdata->target_gain = 0.0;
		pdata->start_gain = 0.0;
		pdata->end_gain = 0.0;
		pdata->r128 = 0;
		pdata->reset = 1;
		pdata->time_elapsed_ms = 0;
		pdata->prev_o_pos = 0;

		filter->close = filter_close;
		filter->process = filter_process;
		filter->child = pdata;

		mlt_events_listen( properties, filter, "property-changed", (mlt_listener)property_changed );
	}
	else
	{
		if( filter )
		{
			mlt_filter_close( filter );
			filter = NULL;
		}

		free( pdata );
	}

	return filter;
}
예제 #12
0
파일: consumer_multi.c 프로젝트: Enlik/mlt
static mlt_consumer generate_consumer( mlt_consumer consumer, mlt_properties props, int index )
{
    mlt_profile profile = NULL;
    if ( mlt_properties_get( props, "mlt_profile" ) )
        profile = mlt_profile_init( mlt_properties_get( props, "mlt_profile" ) );
    if ( !profile )
        profile = mlt_profile_clone( mlt_service_profile( MLT_CONSUMER_SERVICE(consumer) ) );
    mlt_consumer nested = create_consumer( profile, mlt_properties_get( props, "mlt_service" ),
                                           mlt_properties_get( props, "target" ) );

    if ( nested )
    {
        mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
        mlt_properties nested_props = MLT_CONSUMER_PROPERTIES(nested);
        char key[30];

        snprintf( key, sizeof(key), "%d.consumer", index );
        mlt_properties_set_data( properties, key, nested, 0, (mlt_destructor) mlt_consumer_close, NULL );
        snprintf( key, sizeof(key), "%d.profile", index );
        mlt_properties_set_data( properties, key, profile, 0, (mlt_destructor) mlt_profile_close, NULL );

        mlt_properties_set_int( nested_props, "put_mode", 1 );
        mlt_properties_pass_list( nested_props, properties, "terminate_on_pause" );
        mlt_properties_set( props, "consumer", NULL );
        // set mlt_profile before other properties to facilitate presets
        mlt_properties_pass_list( nested_props, props, "mlt_profile" );
        mlt_properties_inherit( nested_props, props );

        attach_normalisers( profile, MLT_CONSUMER_SERVICE(nested) );

        // Relay the first available consumer-frame-show event
        mlt_event event = mlt_properties_get_data( properties, "frame-show-event", NULL );
        if ( !event )
        {
            event = mlt_events_listen( nested_props, properties, "consumer-frame-show", (mlt_listener) on_frame_show );
            mlt_properties_set_data( properties, "frame-show-event", event, 0, /*mlt_event_close*/ NULL, NULL );
        }
    }
    else
    {
        mlt_profile_close( profile );
    }
    return nested;
}
예제 #13
0
    mlt_producer producer_decklink_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
    {
        // Allocate the producer
        DeckLinkProducer* decklink = new DeckLinkProducer();
        mlt_producer producer = (mlt_producer) calloc( 1, sizeof( *producer ) );

        // If allocated and initializes
        if ( decklink && !mlt_producer_init( producer, decklink ) )
        {
            if ( decklink->open( arg? atoi( arg ) : 0 ) )
            {
                mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );

                // Close DeckLink and defer re-open to get_frame
                delete decklink;
                producer->child = NULL;

                // Set callbacks
                producer->close = (mlt_destructor) producer_close;
                producer->get_frame = get_frame;

                // Set properties
                mlt_properties_set( properties, "resource", (arg && strcmp( arg, ""))? arg : "0" );
                mlt_properties_set_int( properties, "channels", 2 );
                mlt_properties_set_int( properties, "buffer", 25 );
                mlt_properties_set_int( properties, "prefill", 25 );

                // These properties effectively make it infinite.
                mlt_properties_set_int( properties, "length", INT_MAX );
                mlt_properties_set_int( properties, "out", INT_MAX - 1 );
                mlt_properties_set( properties, "eof", "loop" );

                mlt_event event = mlt_events_listen( properties, properties, "property-changed", (mlt_listener) on_property_changed );
                mlt_properties_set_data( properties, "list-devices-event", event, 0, NULL, NULL );
            }
        }

        return producer;
    }
예제 #14
0
파일: producer_consumer.c 프로젝트: aib/mlt
static int get_frame( mlt_producer self, mlt_frame_ptr frame, int index )
{
	mlt_properties properties = MLT_PRODUCER_PROPERTIES(self);
	context cx = mlt_properties_get_data( properties, "context", NULL );

	if ( !cx )
	{
		// Allocate and initialize our context
		cx = mlt_pool_alloc( sizeof( struct context_s ) );
		memset( cx, 0, sizeof( *cx ) );
		mlt_properties_set_data( properties, "context", cx, 0, mlt_pool_release, NULL );
		cx->self = self;
		char *profile_name = mlt_properties_get( properties, "profile" );
		if ( !profile_name )
			profile_name = mlt_properties_get( properties, "mlt_profile" );
		mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( self ) );

		if ( profile_name )
		{
			cx->profile = mlt_profile_init( profile_name );
			cx->profile->is_explicit = 1;
		}
		else
		{
			cx->profile = mlt_profile_clone( profile );
			cx->profile->is_explicit = 0;
		}

		// Encapsulate a real producer for the resource
		cx->producer = mlt_factory_producer( cx->profile, NULL,
			mlt_properties_get( properties, "resource" ) );
		if ( ( profile_name && !strcmp( profile_name, "auto" ) ) ||
			mlt_properties_get_int( properties, "autoprofile" ) )
		{
			mlt_profile_from_producer( cx->profile, cx->producer );
			mlt_producer_close( cx->producer );
			cx->producer = mlt_factory_producer( cx->profile, NULL,	mlt_properties_get( properties, "resource" ) );
		}

		// Since we control the seeking, prevent it from seeking on its own
		mlt_producer_set_speed( cx->producer, 0 );
		cx->audio_position = -1;

		// We will encapsulate a consumer
		cx->consumer = mlt_consumer_new( cx->profile );
		// Do not use _pass_list on real_time so that it defaults to 0 in the absence of
		// an explicit real_time property.
		mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( cx->consumer ), "real_time",
			mlt_properties_get_int( properties, "real_time" ) );
		mlt_properties_pass_list( MLT_CONSUMER_PROPERTIES( cx->consumer ), properties,
			"buffer, prefill, deinterlace_method, rescale" );

		mlt_properties_pass( MLT_CONSUMER_PROPERTIES( cx->consumer ), properties, CONSUMER_PROPERTIES_PREFIX );
		mlt_properties_pass( MLT_PRODUCER_PROPERTIES( cx->producer ), properties, PRODUCER_PROPERTIES_PREFIX );
		mlt_events_listen( properties, self, "property-changed", ( mlt_listener )property_changed );

		// Connect it all together
		mlt_consumer_connect( cx->consumer, MLT_PRODUCER_SERVICE( cx->producer ) );
		mlt_consumer_start( cx->consumer );
	}

	// Generate a frame
	*frame = mlt_frame_init( MLT_PRODUCER_SERVICE( self ) );
	if ( *frame )
	{
		// Seek the producer to the correct place
		// Calculate our positions
		double actual_position = (double) mlt_producer_frame( self );
		if ( mlt_producer_get_speed( self ) != 0 )
			actual_position *= mlt_producer_get_speed( self );
		mlt_position need_first = floor( actual_position );
		mlt_producer_seek( cx->producer,
			lrint( need_first * mlt_profile_fps( cx->profile ) / mlt_producer_get_fps( self ) ) );

		// Get the nested frame
		mlt_frame nested_frame = mlt_consumer_rt_frame( cx->consumer );

		// Stack the producer and our methods on the nested frame
		mlt_frame_push_service( *frame, nested_frame );
		mlt_frame_push_service( *frame, cx );
		mlt_frame_push_get_image( *frame, get_image );
		mlt_frame_push_audio( *frame, nested_frame );
		mlt_frame_push_audio( *frame, cx );
		mlt_frame_push_audio( *frame, get_audio );
		
		// Give the returned frame temporal identity
		mlt_frame_set_position( *frame, mlt_producer_position( self ) );
		
		// Store the nested frame on the produced frame for destruction
		mlt_properties frame_props = MLT_FRAME_PROPERTIES( *frame );
		mlt_properties_set_data( frame_props, "_producer_consumer.frame", nested_frame, 0, (mlt_destructor) mlt_frame_close, NULL );

		// Inform the normalizers about our video properties
		mlt_properties_set_double( frame_props, "aspect_ratio", mlt_profile_sar( cx->profile ) );
		mlt_properties_set_int( frame_props, "width", cx->profile->width );
		mlt_properties_set_int( frame_props, "height", cx->profile->height );
		mlt_properties_set_int( frame_props, "meta.media.width", cx->profile->width );
		mlt_properties_set_int( frame_props, "meta.media.height", cx->profile->height );
		mlt_properties_set_int( frame_props, "progressive", cx->profile->progressive );
	}

	// Calculate the next timecode
	mlt_producer_prepare_next( self );

	return 0;
}
예제 #15
0
파일: melt.c 프로젝트: hrshadhin/mlt
int main( int argc, char **argv )
{
    int i;
    mlt_consumer consumer = NULL;
    FILE *store = NULL;
    char *name = NULL;
    mlt_profile profile = NULL;
    int is_progress = 0;
    int is_silent = 0;
    mlt_profile backup_profile;

    // Handle abnormal exit situations.
    signal( SIGSEGV, abnormal_exit_handler );
    signal( SIGILL, abnormal_exit_handler );
    signal( SIGABRT, abnormal_exit_handler );

    // Construct the factory
    mlt_repository repo = mlt_factory_init( NULL );

#if defined(WIN32) && !defined(MELT_NOSDL)
    is_silent = 1;
#endif

    for ( i = 1; i < argc; i ++ )
    {
        // Check for serialisation switch
        if ( !strcmp( argv[ i ], "-serialise" ) )
        {
            name = argv[ ++ i ];
            if ( name != NULL && strstr( name, ".melt" ) )
                store = fopen( name, "w" );
            else
            {
                if ( name == NULL || name[0] == '-' )
                    store = stdout;
                name = NULL;
            }
        }
        // Look for the profile option
        else if ( !strcmp( argv[ i ], "-profile" ) )
        {
            const char *pname = argv[ ++ i ];
            if ( pname && pname[0] != '-' )
                profile = mlt_profile_init( pname );
        }
        else if ( !strcmp( argv[ i ], "-progress" ) )
        {
            is_progress = 1;
        }
        else if ( !strcmp( argv[ i ], "-progress2" ) )
        {
            is_progress = 2;
        }
        // Look for the query option
        else if ( !strcmp( argv[ i ], "-query" ) )
        {
            const char *pname = argv[ ++ i ];
            if ( pname && pname[0] != '-' )
            {
                if ( !strcmp( pname, "consumers" ) || !strcmp( pname, "consumer" ) )
                    query_services( repo, consumer_type );
                else if ( !strcmp( pname, "filters" ) || !strcmp( pname, "filter" ) )
                    query_services( repo, filter_type );
                else if ( !strcmp( pname, "producers" ) || !strcmp( pname, "producer" ) )
                    query_services( repo, producer_type );
                else if ( !strcmp( pname, "transitions" ) || !strcmp( pname, "transition" ) )
                    query_services( repo, transition_type );
                else if ( !strcmp( pname, "profiles" ) || !strcmp( pname, "profile" ) )
                    query_profiles();
                else if ( !strcmp( pname, "presets" ) || !strcmp( pname, "preset" ) )
                    query_presets();
                else if ( !strncmp( pname, "format", 6 ) )
                    query_formats();
                else if ( !strncmp( pname, "acodec", 6 ) || !strcmp( pname, "audio_codecs" ) )
                    query_acodecs();
                else if ( !strncmp( pname, "vcodec", 6 ) || !strcmp( pname, "video_codecs" ) )
                    query_vcodecs();

                else if ( !strncmp( pname, "consumer=", 9 ) )
                    query_metadata( repo, consumer_type, "consumer", strchr( pname, '=' ) + 1 );
                else if ( !strncmp( pname, "filter=", 7 ) )
                    query_metadata( repo, filter_type, "filter", strchr( pname, '=' ) + 1 );
                else if ( !strncmp( pname, "producer=", 9 ) )
                    query_metadata( repo, producer_type, "producer", strchr( pname, '=' ) + 1 );
                else if ( !strncmp( pname, "transition=", 11 ) )
                    query_metadata( repo, transition_type, "transition", strchr( pname, '=' ) + 1 );
                else if ( !strncmp( pname, "profile=", 8 ) )
                    query_profile( strchr( pname, '=' ) + 1 );
                else if ( !strncmp( pname, "preset=", 7 ) )
                    query_preset( strchr( pname, '=' ) + 1 );
                else
                    goto query_all;
            }
            else
            {
query_all:
                query_services( repo, consumer_type );
                query_services( repo, filter_type );
                query_services( repo, producer_type );
                query_services( repo, transition_type );
                fprintf( stdout, "# You can query the metadata for a specific service using:\n"
                         "# -query <type>=<identifer>\n"
                         "# where <type> is one of: consumer, filter, producer, or transition.\n" );
            }
            goto exit_factory;
        }
        else if ( !strcmp( argv[ i ], "-silent" ) )
        {
            is_silent = 1;
        }
        else if ( !strcmp( argv[ i ], "-verbose" ) )
        {
            mlt_log_set_level( MLT_LOG_VERBOSE );
        }
        else if ( !strcmp( argv[ i ], "-version" ) || !strcmp( argv[ i ], "--version" ) )
        {
            fprintf( stdout, "%s " VERSION "\n"
                     "Copyright (C) 2002-2013 Ushodaya Enterprises Limited\n"
                     "<http://www.mltframework.org/>\n"
                     "This is free software; see the source for copying conditions.  There is NO\n"
                     "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
                     basename( argv[0] ) );
            goto exit_factory;
        }
        else if ( !strcmp( argv[ i ], "-debug" ) )
        {
            mlt_log_set_level( MLT_LOG_DEBUG );
        }
    }
    if ( !is_silent && !isatty( STDIN_FILENO ) && !is_progress )
        is_progress = 1;

    // Create profile if not set explicitly
    if ( getenv( "MLT_PROFILE" ) )
        profile = mlt_profile_init( NULL );
    if ( profile == NULL )
        profile = mlt_profile_init( NULL );
    else
        profile->is_explicit = 1;

    // Look for the consumer option to load profile settings from consumer properties
    backup_profile = mlt_profile_clone( profile );
    load_consumer( &consumer, profile, argc, argv );

    // If the consumer changed the profile, then it is explicit.
    if ( backup_profile && !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->frame_rate_den != backup_profile->frame_rate_den ||
                profile->frame_rate_num != backup_profile->frame_rate_num ||
                profile->colorspace != backup_profile->colorspace ) )
        profile->is_explicit = 1;
    mlt_profile_close( backup_profile );

    // Get melt producer
    if ( argc > 1 )
        melt = mlt_factory_producer( profile, "melt", &argv[ 1 ] );

    if ( melt )
    {
        // Generate an automatic profile if needed.
        if ( ! profile->is_explicit )
        {
            mlt_profile_from_producer( profile, melt );
            mlt_producer_close( melt );
            melt = mlt_factory_producer( profile, "melt", &argv[ 1 ] );
        }

        // Reload the consumer with the fully qualified profile.
        // The producer or auto-profile could have changed the profile.
        load_consumer( &consumer, profile, argc, argv );

        // See if producer has consumer already attached
        if ( !store && !consumer )
        {
            consumer = MLT_CONSUMER( mlt_service_consumer( MLT_PRODUCER_SERVICE( melt ) ) );
            if ( consumer )
            {
                mlt_properties_inc_ref( MLT_CONSUMER_PROPERTIES(consumer) ); // because we explicitly close it
                mlt_properties_set_data( MLT_CONSUMER_PROPERTIES(consumer),
                                         "transport_callback", transport_action, 0, NULL, NULL );
            }
        }

        // If we have no consumer, default to sdl
        if ( store == NULL && consumer == NULL )
            consumer = create_consumer( profile, NULL );
    }

    // Set transport properties on consumer and produder
    if ( consumer != NULL && melt != NULL )
    {
        mlt_properties_set_data( MLT_CONSUMER_PROPERTIES( consumer ), "transport_producer", melt, 0, NULL, NULL );
        mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( melt ), "transport_consumer", consumer, 0, NULL, NULL );
        if ( is_progress )
            mlt_properties_set_int(  MLT_CONSUMER_PROPERTIES( consumer ), "progress", is_progress );
        if ( is_silent )
            mlt_properties_set_int(  MLT_CONSUMER_PROPERTIES( consumer ), "silent", is_silent );
    }

    if ( argc > 1 && melt != NULL && mlt_producer_get_length( melt ) > 0 )
    {
        // Parse the arguments
        for ( i = 1; i < argc; i ++ )
        {
            if ( !strcmp( argv[ i ], "-jack" ) )
            {
                setup_jack_transport( consumer, profile );
            }
            else if ( !strcmp( argv[ i ], "-serialise" ) )
            {
                if ( store != stdout )
                    i ++;
            }
            else
            {
                if ( store != NULL )
                    fprintf( store, "%s\n", argv[ i ] );

                i ++;

                while ( argv[ i ] != NULL && argv[ i ][ 0 ] != '-' )
                {
                    if ( store != NULL )
                        fprintf( store, "%s\n", argv[ i ] );
                    i += 1;
                }

                i --;
            }
        }

        if ( consumer != NULL && store == NULL )
        {
            // Get melt's properties
            mlt_properties melt_props = MLT_PRODUCER_PROPERTIES( melt );

            // Get the last group
            mlt_properties group = mlt_properties_get_data( melt_props, "group", 0 );

            // Apply group settings
            mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
            mlt_properties_inherit( properties, group );

            // Connect consumer to melt
            mlt_consumer_connect( consumer, MLT_PRODUCER_SERVICE( melt ) );

            // Start the consumer
            mlt_events_listen( properties, consumer, "consumer-fatal-error", ( mlt_listener )on_fatal_error );
            if ( mlt_consumer_start( consumer ) == 0 )
            {
                // Try to exit gracefully upon these signals
                signal( SIGINT, stop_handler );
                signal( SIGTERM, stop_handler );
#ifndef WIN32
                signal( SIGHUP, stop_handler );
                signal( SIGPIPE, stop_handler );
#endif

                // Transport functionality
                transport( melt, consumer );

                // Stop the consumer
                mlt_consumer_stop( consumer );
            }
        }
        else if ( store != NULL && store != stdout && name != NULL )
        {
            fprintf( stderr, "Project saved as %s.\n", name );
            fclose( store );
        }
    }
    else
    {
        show_usage( argv[0] );
    }

    // Disconnect producer from consumer to prevent ref cycles from closing services
    if ( consumer )
    {
        mlt_consumer_connect( consumer, NULL );
        mlt_events_fire( MLT_CONSUMER_PROPERTIES(consumer), "consumer-cleanup", NULL);
    }

    // Close the producer
    if ( melt != NULL )
        mlt_producer_close( melt );

    // Close the consumer
    if ( consumer != NULL )
        mlt_consumer_close( consumer );

    // Close the factory
    mlt_profile_close( profile );

exit_factory:

// Workaround qmelt on OS X from crashing at exit.
#if !defined(__MACH__) || !defined(QT_GUI_LIB)
    mlt_factory_close( );
#endif

    return 0;
}
예제 #16
0
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, "&lt;producer&gt;" ) ) ) )
		{
			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;
}
예제 #17
0
mlt_consumer consumer_sdl_audio_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 );

		// Ensure we don't join on a non-running object
		self->joined = 1;
		
		// Allow thread to be started/stopped
		parent->start = consumer_start;
		parent->stop = consumer_stop;
		parent->is_stopped = consumer_is_stopped;
		parent->purge = consumer_purge;

		// Initialize the refresh handler
		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 );

		// Return the consumer produced
		return parent;
	}

	// malloc or consumer init failed
	free( self );

	// Indicate failure
	return NULL;
}