Ejemplo n.º 1
0
mlt_producer mlt_producer_cut( mlt_producer self, int in, int out )
{
	mlt_producer result = mlt_producer_new( mlt_service_profile( MLT_PRODUCER_SERVICE( self ) ) );
	mlt_producer parent = mlt_producer_cut_parent( self );
	mlt_properties properties = MLT_PRODUCER_PROPERTIES( result );
	mlt_properties parent_props = MLT_PRODUCER_PROPERTIES( parent );

	mlt_properties_set_lcnumeric( properties,
		mlt_properties_get_lcnumeric( MLT_PRODUCER_PROPERTIES( self ) ) );

	mlt_events_block( MLT_PRODUCER_PROPERTIES( result ), MLT_PRODUCER_PROPERTIES( result ) );
	// Special case - allow for a cut of the entire producer (this will squeeze all other cuts to 0)
	if ( in <= 0 )
		in = 0;
	if ( ( out < 0 || out >= mlt_producer_get_length( parent ) ) && !mlt_producer_is_blank( self ) )
		out = mlt_producer_get_length( parent ) - 1;

	mlt_properties_inc_ref( parent_props );
	mlt_properties_set_int( properties, "_cut", 1 );
	mlt_properties_set_data( properties, "_cut_parent", parent, 0, ( mlt_destructor )mlt_producer_close, NULL );
	mlt_properties_set_position( properties, "length", mlt_properties_get_position( parent_props, "length" ) );
	mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( parent_props, "aspect_ratio" ) );
	mlt_producer_set_in_and_out( result, in, out );

	return result;
}
Ejemplo n.º 2
0
mlt_frame mlt_filter_process( mlt_filter self, mlt_frame frame )
{
	mlt_properties properties = MLT_FILTER_PROPERTIES( self );
	int disable = mlt_properties_get_int( properties, "disable" );
	const char *unique_id = mlt_properties_get( properties, "_unique_id" );
	mlt_position position = mlt_frame_get_position( frame );
	char name[30];

	// Make the properties key from unique id
	snprintf( name, sizeof(name), "pos.%s", unique_id );
	name[sizeof(name) -1] = '\0';

	// Save the position on the frame
	mlt_properties_set_position( MLT_FRAME_PROPERTIES( frame ), name, position );

	if ( disable || self->process == NULL )
	{
		return frame;
	}
	else
	{
		// Add a reference to this filter on the frame
		mlt_properties_inc_ref( MLT_FILTER_PROPERTIES(self) );
		snprintf( name, sizeof(name), "filter.%s", unique_id );
		name[sizeof(name) -1] = '\0';
		mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), name, self, 0,
			(mlt_destructor) mlt_filter_close, NULL );

		return self->process( self, frame );
	}
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
mlt_service MltLoader::pop_mlt_registry(const char* uuid)
{
	if (!uuid || !strlen(uuid) ) return NULL;

	mlt_service ret = NULL;
	{
		Lock lk(&mlt_register_lock);
		hash_map<string, MltSvcWrap>::iterator it = mlt_register.find(string(uuid));
		if ( it != mlt_register.end() ) {
			ret = it->second.obj;
			mlt_properties_inc_ref(mlt_service_properties(ret));
			mlt_register.erase(it);
		}
	}
	return ret;
}
Ejemplo n.º 6
0
static mlt_frame process( mlt_filter filter, mlt_frame frame )
{
	// Set a default colorspace on the frame if not yet set by the producer.
	// The producer may still change it during get_image.
	// This way we do not have to modify each producer to set a valid colorspace.
	mlt_properties properties = MLT_FRAME_PROPERTIES(frame);
	if ( mlt_properties_get_int( properties, "colorspace" ) <= 0 )
		mlt_properties_set_int( properties, "colorspace", mlt_service_profile( MLT_FILTER_SERVICE(filter) )->colorspace );

	frame->convert_image = convert_image;

	mlt_filter cpu_csc = (mlt_filter) mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), "cpu_csc", NULL );
	mlt_properties_inc_ref( MLT_FILTER_PROPERTIES(cpu_csc) );
	mlt_properties_set_data( properties, "cpu_csc", cpu_csc, 0,
		(mlt_destructor) mlt_filter_close, NULL );

	return frame;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
mlt_frame frame_cache_get_frame( frame_cache self, mlt_position position )
{
	// Return NULL if cache miss/fail
	mlt_frame frame = NULL;

	if ( self == NULL )
		return frame;

	if ( self->frames_total > 0 )
	{
		ssize_t index = frame_cache_frame_index( self, position );
		if ( index != -1 )
			frame = self->frames[ index ];
	}

	// We managed to get frame from cache, so retain it to share ownership with the client
	if ( frame != NULL )
	{
		mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( frame ) );
	}

	return frame;
}
Ejemplo n.º 9
0
Archivo: melt.c Proyecto: 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;
}
Ejemplo n.º 10
0
static int filter_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;

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

	// Get the properties of the filter
	mlt_properties properties = MLT_FILTER_PROPERTIES( this );

	mlt_service_lock( MLT_FILTER_SERVICE( this ) );

	// Get the producer from the filter
	mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );

	// Get the composite from the filter
	mlt_transition composite = mlt_properties_get_data( properties, "composite", NULL );

	// Get the resource to use
	char *resource = mlt_properties_get( properties, "resource" );

	// Get the old resource
	char *old_resource = mlt_properties_get( properties, "_old_resource" );

	// Create a composite if we don't have one
	if ( composite == NULL )
	{
		// Create composite via the factory
		mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
		composite = mlt_factory_transition( profile, "composite", NULL );

		// Register the composite for reuse/destruction
		if ( composite != NULL )
			mlt_properties_set_data( properties, "composite", composite, 0, ( mlt_destructor )mlt_transition_close, NULL );
	}

	// If we have one
	if ( composite != NULL )
	{
		// Get the properties
		mlt_properties composite_properties = MLT_TRANSITION_PROPERTIES( composite );

		// Pass all the composite. properties on the filter down
		mlt_properties_pass( composite_properties, properties, "composite." );

		if ( mlt_properties_get( properties, "composite.out" ) == NULL )
			mlt_properties_set_int( composite_properties, "out", mlt_properties_get_int( properties, "_out" ) );

		// Force a refresh
		mlt_properties_set_int( composite_properties, "refresh", 1 );
	}

	// Create a producer if don't have one
	if ( producer == NULL || ( old_resource != NULL && strcmp( resource, old_resource ) ) )
	{
		// Get the factory producer service
		char *factory = mlt_properties_get( properties, "factory" );

		// Create the producer
		mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
		producer = mlt_factory_producer( profile, factory, resource );

		// If we have one
		if ( producer != NULL )
		{
			// Register the producer for reuse/destruction
			mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );

			// Ensure that we loop
			mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ), "eof", "loop" );

			// Set the old resource
			mlt_properties_set( properties, "_old_resource", resource );
		}
	}

	if ( producer != NULL )
	{
		// Get the producer properties
		mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );

		// Now pass all producer. properties on the filter down
		mlt_properties_pass( producer_properties, properties, "producer." );
	}

	mlt_service_unlock( MLT_FILTER_SERVICE( this ) );

	// Only continue if we have both producer and composite
	if ( composite != NULL && producer != NULL )
	{
		// Get the service of the producer
		mlt_service service = MLT_PRODUCER_SERVICE( producer );

		// We will get the 'b frame' from the producer
		mlt_frame b_frame = NULL;

		// Get the original producer position
		mlt_position position = mlt_filter_get_position( this, frame );

		// Make sure the producer is in the correct position
		mlt_producer_seek( producer, position );

		// Resetting position to appease the composite transition
		mlt_frame_set_position( frame, position );

		// Get the b frame and process with composite if successful
		if ( mlt_service_get_frame( service, &b_frame, 0 ) == 0 )
		{
			// Get the a and b frame properties
			mlt_properties a_props = MLT_FRAME_PROPERTIES( frame );
			mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
			mlt_profile profile = mlt_service_profile( service );

			// Set the b frame to be in the same position and have same consumer requirements
			mlt_frame_set_position( b_frame, position );
			mlt_properties_set_int( b_props, "consumer_deinterlace", mlt_properties_get_int( a_props, "consumer_deinterlace" ) || mlt_properties_get_int( properties, "deinterlace" ) );

			// Check for the special case - no aspect ratio means no problem :-)
			if ( mlt_frame_get_aspect_ratio( b_frame ) == 0 )
				mlt_frame_set_aspect_ratio( b_frame, mlt_profile_sar( profile ) );
			if ( mlt_frame_get_aspect_ratio( frame ) == 0 )
				mlt_frame_set_aspect_ratio( frame, mlt_profile_sar( profile ) );

			if ( mlt_properties_get_int( properties, "distort" ) )
			{
				mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( composite ), "distort", 1 );
				mlt_properties_set_int( a_props, "distort", 1 );
				mlt_properties_set_int( b_props, "distort", 1 );
			}

			*format = mlt_image_yuv422;
			if ( mlt_properties_get_int( properties, "reverse" ) == 0 )
			{
				// Apply all filters that are attached to this filter to the b frame
				mlt_service_apply_filters( MLT_FILTER_SERVICE( this ), b_frame, 0 );

				// Process the frame
				mlt_transition_process( composite, frame, b_frame );

				// Get the image
				error = mlt_frame_get_image( frame, image, format, width, height, 1 );
			}
			else
			{
				char temp[ 132 ];
				int count = 0;
				uint8_t *alpha = NULL;
				const char *rescale = mlt_properties_get( a_props, "rescale.interp" );
				if ( rescale == NULL || !strcmp( rescale, "none" ) )
					rescale = "hyper";
				mlt_transition_process( composite, b_frame, frame );
				mlt_properties_set_int( a_props, "consumer_deinterlace", 1 );
				mlt_properties_set_int( b_props, "consumer_deinterlace", 1 );
				mlt_properties_set( a_props, "rescale.interp", rescale );
				mlt_properties_set( b_props, "rescale.interp", rescale );
				mlt_service_apply_filters( MLT_FILTER_SERVICE( this ), b_frame, 0 );
				error = mlt_frame_get_image( b_frame, image, format, width, height, 1 );
				alpha = mlt_frame_get_alpha_mask( b_frame );
				mlt_frame_set_image( frame, *image, *width * *height * 2, NULL );
				mlt_frame_set_alpha( frame, alpha, *width * *height, NULL );
				mlt_properties_set_int( a_props, "width", *width );
				mlt_properties_set_int( a_props, "height", *height );
				mlt_properties_set_int( a_props, "progressive", 1 );
				mlt_properties_inc_ref( b_props );
				strcpy( temp, "_b_frame" );
				while( mlt_properties_get_data( a_props, temp, NULL ) != NULL )
					sprintf( temp, "_b_frame%d", count ++ );
				mlt_properties_set_data( a_props, temp, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
			}
		}

		// Close the b frame
		mlt_frame_close( b_frame );
	}
	else
	{
		// Get the image from the frame without running fx
		error = mlt_frame_get_image( frame, image, format, width, height, 1 );
	}

	return error;
}
Ejemplo n.º 11
0
static void *consumer_worker_thread( void *arg )
{
	// The argument is the consumer
	mlt_consumer self = arg;

	// Get the properties of the consumer
	mlt_properties properties = MLT_CONSUMER_PROPERTIES( self );

	// Get the width and height
	int width = mlt_properties_get_int( properties, "width" );
	int height = mlt_properties_get_int( properties, "height" );
	mlt_image_format format = self->format;

	// See if video is turned off
	int video_off = mlt_properties_get_int( properties, "video_off" );
	int preview_off = mlt_properties_get_int( properties, "preview_off" );
	int preview_format = mlt_properties_get_int( properties, "preview_format" );

	// General frame variable
	mlt_frame frame = NULL;
	uint8_t *image = NULL;

	if ( preview_off && preview_format != 0 )
		format = preview_format;

	// Continue to read ahead
	while ( self->ahead )
	{
		// Get the next unprocessed frame from the work queue
		pthread_mutex_lock( &self->queue_mutex );
		int index = first_unprocessed_frame( self );
		while ( self->ahead && index >= mlt_deque_count( self->queue ) )
		{
			mlt_log_debug( MLT_CONSUMER_SERVICE(self), "waiting in worker index = %d queue count = %d\n",
				index, mlt_deque_count( self->queue ) );
			pthread_cond_wait( &self->queue_cond, &self->queue_mutex );
			index = first_unprocessed_frame( self );
		}

		// Mark the frame for processing
		frame = mlt_deque_peek( self->queue, index );
		if ( frame )
		{
			mlt_log_debug( MLT_CONSUMER_SERVICE(self), "worker processing index = %d frame %d queue count = %d\n",
				index, mlt_frame_get_position(frame), mlt_deque_count( self->queue ) );
			frame->is_processing = 1;
			mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( frame ) );
		}
		pthread_mutex_unlock( &self->queue_mutex );

		// If there's no frame, we're probably stopped...
		if ( frame == NULL )
			continue;

#ifdef DEINTERLACE_ON_NOT_NORMAL_SPEED
		// All non normal playback frames should be shown
		if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "_speed" ) != 1 )
			mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "consumer_deinterlace", 1 );
#endif

		// Get the image
		if ( !video_off )
		{
			// Fetch width/height again
			width = mlt_properties_get_int( properties, "width" );
			height = mlt_properties_get_int( properties, "height" );
			mlt_events_fire( MLT_CONSUMER_PROPERTIES( self ), "consumer-frame-render", frame, NULL );
			mlt_frame_get_image( frame, &image, &format, &width, &height, 0 );
		}
		mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 1 );
		mlt_frame_close( frame );

		// Tell a waiting thread (non-realtime main consumer thread) that we are done.
		pthread_mutex_lock( &self->done_mutex );
		pthread_cond_broadcast( &self->done_cond );
		pthread_mutex_unlock( &self->done_mutex );
	}

	return NULL;
}
Ejemplo n.º 12
0
mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
{
	mlt_frame new_frame = mlt_frame_init( NULL );
	mlt_properties properties = MLT_FRAME_PROPERTIES( self );
	mlt_properties new_props = MLT_FRAME_PROPERTIES( new_frame );
	void *data, *copy;
	int size;

	mlt_properties_inherit( new_props, properties );

	// Carry over some special data properties for the multi consumer.
	mlt_properties_set_data( new_props, "_producer",
		mlt_frame_get_original_producer( self ), 0, NULL, NULL );
	mlt_properties_set_data( new_props, "movit.convert",
		mlt_properties_get_data( properties, "movit.convert", NULL), 0, NULL, NULL );

	if ( is_deep )
	{
		data = mlt_properties_get_data( properties, "audio", &size );
		if ( data )
		{
			if ( !size )
				size = mlt_audio_format_size( mlt_properties_get_int( properties, "audio_format" ),
					mlt_properties_get_int( properties, "audio_samples" ),
					mlt_properties_get_int( properties, "audio_channels" ) );
			copy = mlt_pool_alloc( size );
			memcpy( copy, data, size );
			mlt_properties_set_data( new_props, "audio", copy, size, mlt_pool_release, NULL );
		}
		data = mlt_properties_get_data( properties, "image", &size );
		if ( data )
		{
			if ( ! size )
				size = mlt_image_format_size( mlt_properties_get_int( properties, "format" ),
					mlt_properties_get_int( properties, "width" ),
					mlt_properties_get_int( properties, "height" ), NULL );
			copy = mlt_pool_alloc( size );
			memcpy( copy, data, size );
			mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );

			data = mlt_properties_get_data( properties, "alpha", &size );
			if ( data )
			{
				if ( ! size )
					size = mlt_properties_get_int( properties, "width" ) *
						mlt_properties_get_int( properties, "height" );
				copy = mlt_pool_alloc( size );
				memcpy( copy, data, size );
				mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
			};
		}
	}
	else
	{
		// This frame takes a reference on the original frame since the data is a shallow copy.
		mlt_properties_inc_ref( properties );
		mlt_properties_set_data( new_props, "_cloned_frame", self, 0,
			(mlt_destructor) mlt_frame_close, NULL );

		// Copy properties
		data = mlt_properties_get_data( properties, "audio", &size );
		mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
		data = mlt_properties_get_data( properties, "image", &size );
		mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
		data = mlt_properties_get_data( properties, "alpha", &size );
		mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );
	}

	return new_frame;
}
Ejemplo n.º 13
0
int mlt_service_get_frame( mlt_service self, mlt_frame_ptr frame, int index )
{
	int result = 0;

	// Lock the service
	mlt_service_lock( self );

	// Ensure that the frame is NULL
	*frame = NULL;

	// Only process if we have a valid service
	if ( self != NULL && self->get_frame != NULL )
	{
		mlt_properties properties = MLT_SERVICE_PROPERTIES( self );
		mlt_position in = mlt_properties_get_position( properties, "in" );
		mlt_position out = mlt_properties_get_position( properties, "out" );
		mlt_position position = mlt_service_identify( self ) == producer_type ? mlt_producer_position( MLT_PRODUCER( self ) ) : -1;

		result = self->get_frame( self, frame, index );

		if ( result == 0 )
		{
			mlt_properties_inc_ref( properties );
			properties = MLT_FRAME_PROPERTIES( *frame );
			
			if ( in >=0 && out > 0 )
			{
				mlt_properties_set_position( properties, "in", in );
				mlt_properties_set_position( properties, "out", out );
			}
			mlt_service_apply_filters( self, *frame, 1 );
			mlt_deque_push_back( MLT_FRAME_SERVICE_STACK( *frame ), self );
			
			if ( mlt_service_identify( self ) == producer_type &&
			     mlt_properties_get_int( MLT_SERVICE_PROPERTIES( self ), "_need_previous_next" ) )
			{
				// Save the new position from self->get_frame
				mlt_position new_position = mlt_producer_position( MLT_PRODUCER( self ) );
				
				// Get the preceding frame, unfiltered
				mlt_frame previous_frame;
				mlt_producer_seek( MLT_PRODUCER(self), position - 1 );
				result = self->get_frame( self, &previous_frame, index );
				if ( !result )
					mlt_properties_set_data( properties, "previous frame",
						previous_frame, 0, ( mlt_destructor ) mlt_frame_close, NULL );

				// Get the following frame, unfiltered
				mlt_frame next_frame;
				mlt_producer_seek( MLT_PRODUCER(self), position + 1 );
				result = self->get_frame( self, &next_frame, index );
				if ( !result )
				{
					mlt_properties_set_data( properties, "next frame",
						next_frame, 0, ( mlt_destructor ) mlt_frame_close, NULL );
				}
				
				// Restore the new position
				mlt_producer_seek( MLT_PRODUCER(self), new_position );
			}
		}
	}

	// Make sure we return a frame
	if ( *frame == NULL )
		*frame = mlt_frame_init( self );

	// Unlock the service
	mlt_service_unlock( self );

	return result;
}
Ejemplo n.º 14
0
int mlt_service_insert_producer( mlt_service self, mlt_service producer, int index )
{
	// Get the service base
	mlt_service_base *base = self->local;

	if ( index >= base->count )
		return mlt_service_connect_producer( self, producer, index );

	int i = 0;

	// Special case 'track' index - only works for last filter(s) in a particular chain
	// but allows a filter to apply to the output frame regardless of which track it comes from
	if ( index == -1 )
		index = 0;

	// Check if the producer is already registered with this service.
	for ( i = 0; i < base->count; i ++ )
		if ( base->in[ i ] == producer )
			return 3;

	// Allocate space if needed.
	if ( base->count + 1 > base->size )
	{
		int new_size = base->size + 10;
		base->in = realloc( base->in, new_size * sizeof( mlt_service ) );
		if ( base->in != NULL )
		{
			memset( &base->in[ base->size ], 0, new_size - base->size );
			base->size = new_size;
		}
	}

	// If we have space, assign the input
	if ( base->in && index >= 0 && index < base->size )
	{
		// Increment the reference count on this producer.
		if ( producer != NULL )
			mlt_properties_inc_ref( MLT_SERVICE_PROPERTIES( producer ) );

		// Disconnect the producer from its consumer.
		mlt_service_disconnect( producer );

		// Make room in the list for the producer.
		memmove( &base->in[ index + 1 ], &base->in[ index ],
				( base->count - index ) * sizeof( mlt_service ) );

		// Add the service to index specified.
		base->in[ index ] = producer;

		// Increase the number of active tracks.
		base->count ++;

		// Connect the producer to its connected consumer.
		mlt_service_connect( producer, self );

		// Inform caller that all went well
		return 0;
	}
	else
	{
		return -1;
	}
}
Ejemplo n.º 15
0
int mlt_service_connect_producer( mlt_service self, mlt_service producer, int index )
{
	int i = 0;

	// Get the service base
	mlt_service_base *base = self->local;

	// Special case 'track' index - only works for last filter(s) in a particular chain
	// but allows a filter to apply to the output frame regardless of which track it comes from
	if ( index == -1 )
		index = 0;

	// Check if the producer is already registered with this service
	for ( i = 0; i < base->count; i ++ )
		if ( base->in[ i ] == producer )
			return 3;

	// Allocate space
	if ( index >= base->size )
	{
		int new_size = base->size + index + 10;
		base->in = realloc( base->in, new_size * sizeof( mlt_service ) );
		if ( base->in != NULL )
		{
			for ( i = base->size; i < new_size; i ++ )
				base->in[ i ] = NULL;
			base->size = new_size;
		}
	}

	// If we have space, assign the input
	if ( base->in != NULL && index >= 0 && index < base->size )
	{
		// Get the current service
		mlt_service current = ( index < base->count )? base->in[ index ] : NULL;

		// Increment the reference count on this producer
		if ( producer != NULL )
			mlt_properties_inc_ref( MLT_SERVICE_PROPERTIES( producer ) );

		// Now we disconnect the producer service from its consumer
		mlt_service_disconnect( producer );

		// Add the service to index specified
		base->in[ index ] = producer;

		// Determine the number of active tracks
		if ( index >= base->count )
			base->count = index + 1;

		// Now we connect the producer to its connected consumer
		mlt_service_connect( producer, self );

		// Close the current service
		mlt_service_close( current );

		// Inform caller that all went well
		return 0;
	}
	else
	{
		return -1;
	}
}