예제 #1
0
파일: filter_resize.c 프로젝트: aib/mlt
static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
{
	// Store the aspect ratio reported by the source
	mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( frame ), mlt_frame_get_aspect_ratio( frame ) );

	// Push this on to the service stack
	mlt_frame_push_service( frame, filter );

	// Push the get_image method on to the stack
	mlt_frame_push_get_image( frame, filter_get_image );

	return frame;
}
예제 #2
0
파일: filter_shape.c 프로젝트: bjoern-r/mlt
static inline double smoothstep( const double e1, const double e2, const double a )
{
    if ( a < e1 ) return 0.0;
    if ( a > e2 ) return 1.0;
    double v = ( a - e1 ) / ( e2 - e1 );
    return ( v * v * ( 3 - 2 * v ) );
}

/** Get the images and apply the luminance of the mask to the alpha of the frame.
*/

static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
	// Fetch the data from the stack (mix, mask, filter)
	double mix = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( this ) );
	mlt_frame mask = mlt_frame_pop_service( this );
	mlt_filter filter = mlt_frame_pop_service( this );

	// Obtain the constants
	double softness = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "softness" );
	int use_luminance = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "use_luminance" );
	int invert = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "invert" ) * 255;

	// Render the frame
	*format = mlt_image_yuv422;
	if ( mlt_frame_get_image( this, image, format, width, height, writable ) == 0 && ( !use_luminance || ( int )mix != 1 ) )
	{
		// Get the alpha mask of the source
		uint8_t *alpha = mlt_frame_get_alpha_mask( this );
예제 #3
0
파일: mlt_tractor.c 프로젝트: elfring/mlt
static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track )
{
	mlt_tractor self = parent->child;

	// We only respond to the first track requests
	if ( track == 0 && self->producer != NULL )
	{
		int i = 0;
		int done = 0;
		mlt_frame temp = NULL;
		int count = 0;
		int image_count = 0;

		// Get the properties of the parent producer
		mlt_properties properties = MLT_PRODUCER_PROPERTIES( parent );

		// Try to obtain the multitrack associated to the tractor
		mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL );

		// Or a specific producer
		mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );

		// Determine whether this tractor feeds to the consumer or stops here
		int global_feed = mlt_properties_get_int( properties, "global_feed" );

		// If we don't have one, we're in trouble...
		if ( multitrack != NULL )
		{
			// The output frame will hold the 'global' data feeds (ie: those which are targetted for the final frame)
			mlt_deque data_queue = mlt_deque_init( );

			// Used to garbage collect all frames
			char label[ 30 ];

			// Get the id of the tractor
			char *id = mlt_properties_get( properties, "_unique_id" );

			// Will be used to store the frame properties object
			mlt_properties frame_properties = NULL;

			// We'll store audio and video frames to use here
			mlt_frame audio = NULL;
			mlt_frame video = NULL;
			mlt_frame first_video = NULL;

			// Temporary properties
			mlt_properties temp_properties = NULL;

			// Get the multitrack's producer
			mlt_producer target = MLT_MULTITRACK_PRODUCER( multitrack );
			mlt_producer_seek( target, mlt_producer_frame( parent ) );
			mlt_producer_set_speed( target, mlt_producer_get_speed( parent ) );

			// We will create one frame and attach everything to it
			*frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) );

			// Get the properties of the frame
			frame_properties = MLT_FRAME_PROPERTIES( *frame );

			// Loop through each of the tracks we're harvesting
			for ( i = 0; !done; i ++ )
			{
				// Get a frame from the producer
				mlt_service_get_frame( self->producer, &temp, i );

				// Get the temporary properties
				temp_properties = MLT_FRAME_PROPERTIES( temp );

				// Pass all unique meta properties from the producer's frame to the new frame
				mlt_properties_lock( temp_properties );
				int props_count = mlt_properties_count( temp_properties );
				int j;
				for ( j = 0; j < props_count; j ++ )
				{
					char *name = mlt_properties_get_name( temp_properties, j );
					if ( !strncmp( name, "meta.", 5 ) && !mlt_properties_get( frame_properties, name ) )
						mlt_properties_set( frame_properties, name, mlt_properties_get_value( temp_properties, j ) );
				}
				mlt_properties_unlock( temp_properties );

				// Copy the format conversion virtual functions
				if ( ! (*frame)->convert_image && temp->convert_image )
					(*frame)->convert_image = temp->convert_image;
				if ( ! (*frame)->convert_audio && temp->convert_audio )
					(*frame)->convert_audio = temp->convert_audio;

				// Check for last track
				done = mlt_properties_get_int( temp_properties, "last_track" );

				// Handle fx only tracks
				if ( mlt_properties_get_int( temp_properties, "fx_cut" ) )
				{
					int hide = ( video == NULL ? 1 : 0 ) | ( audio == NULL ? 2 : 0 );
					mlt_properties_set_int( temp_properties, "hide", hide );
				}

				// We store all frames with a destructor on the output frame
				sprintf( label, "_%s_%d", id, count ++ );
				mlt_properties_set_data( frame_properties, label, temp, 0, ( mlt_destructor )mlt_frame_close, NULL );

				// We want to append all 'final' feeds to the global queue
				if ( !done && mlt_properties_get_data( temp_properties, "data_queue", NULL ) != NULL )
				{
					// Move the contents of this queue on to the output frames data queue
					mlt_deque sub_queue = mlt_properties_get_data( MLT_FRAME_PROPERTIES( temp ), "data_queue", NULL );
					mlt_deque temp = mlt_deque_init( );
					while ( global_feed && mlt_deque_count( sub_queue ) )
					{
						mlt_properties p = mlt_deque_pop_back( sub_queue );
						if ( mlt_properties_get_int( p, "final" ) )
							mlt_deque_push_back( data_queue, p );
						else
							mlt_deque_push_back( temp, p );
					}
					while( mlt_deque_count( temp ) )
						mlt_deque_push_front( sub_queue, mlt_deque_pop_back( temp ) );
					mlt_deque_close( temp );
				}

				// Now do the same with the global queue but without the conditional behaviour
				if ( mlt_properties_get_data( temp_properties, "global_queue", NULL ) != NULL )
				{
					mlt_deque sub_queue = mlt_properties_get_data( MLT_FRAME_PROPERTIES( temp ), "global_queue", NULL );
					while ( mlt_deque_count( sub_queue ) )
					{
						mlt_properties p = mlt_deque_pop_back( sub_queue );
						mlt_deque_push_back( data_queue, p );
					}
				}

				// Pick up first video and audio frames
				if ( !done && !mlt_frame_is_test_audio( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 2 ) )
				{
					// Order of frame creation is starting to get problematic
					if ( audio != NULL )
					{
						mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), producer_get_audio );
						mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), audio );
					}
					audio = temp;
				}
				if ( !done && !mlt_frame_is_test_card( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 1 ) )
				{
					if ( video != NULL )
					{
						mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), producer_get_image );
						mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), video );
					}
					video = temp;
					if ( first_video == NULL )
						first_video = temp;

					mlt_properties_set_int( MLT_FRAME_PROPERTIES( temp ), "image_count", ++ image_count );
					image_count = 1;
				}
			}

			// Now stack callbacks
			if ( audio != NULL )
			{
				mlt_frame_push_audio( *frame, audio );
				mlt_frame_push_audio( *frame, producer_get_audio );
			}

			if ( video != NULL )
			{
				mlt_properties video_properties = MLT_FRAME_PROPERTIES( first_video );
				mlt_frame_push_service( *frame, video );
				mlt_frame_push_service( *frame, producer_get_image );
				if ( global_feed )
					mlt_properties_set_data( frame_properties, "data_queue", data_queue, 0, NULL, NULL );
				mlt_properties_set_data( video_properties, "global_queue", data_queue, 0, destroy_data_queue, NULL );
				mlt_properties_set_int( frame_properties, "width", mlt_properties_get_int( video_properties, "width" ) );
				mlt_properties_set_int( frame_properties, "height", mlt_properties_get_int( video_properties, "height" ) );
				mlt_properties_pass_list( frame_properties, video_properties, "meta.media.width, meta.media.height" );
				mlt_properties_set_int( frame_properties, "progressive", mlt_properties_get_int( video_properties, "progressive" ) );
				mlt_properties_set_double( frame_properties, "aspect_ratio", mlt_properties_get_double( video_properties, "aspect_ratio" ) );
				mlt_properties_set_int( frame_properties, "image_count", image_count );
				mlt_properties_set_data( frame_properties, "_producer", mlt_frame_get_original_producer( first_video ), 0, NULL, NULL );
			}
			else
			{
				destroy_data_queue( data_queue );
			}

			mlt_frame_set_position( *frame, mlt_producer_frame( parent ) );
			mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_audio", audio == NULL );
			mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", video == NULL );
		}
		else if ( producer != NULL )
		{
			mlt_producer_seek( producer, mlt_producer_frame( parent ) );
			mlt_producer_set_speed( producer, mlt_producer_get_speed( parent ) );
			mlt_service_get_frame( self->producer, frame, track );
		}
		else
		{
			mlt_log( MLT_PRODUCER_SERVICE( parent ), MLT_LOG_ERROR, "tractor without a multitrack!!\n" );
			mlt_service_get_frame( self->producer, frame, track );
		}

		// Prepare the next frame
		mlt_producer_prepare_next( parent );

		// Indicate our found status
		return 0;
	}
	else
	{
		// Generate a test card
		*frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) );
		return 0;
	}
}
예제 #4
0
파일: filter_resize.c 프로젝트: aib/mlt
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
	int error = 0;

	// Get the properties from the frame
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );

	// Pop the top of stack now
	mlt_filter filter = mlt_frame_pop_service( frame );
	mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );

	// Retrieve the aspect ratio
	double aspect_ratio = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( frame ) );
	double consumer_aspect = mlt_profile_sar( mlt_service_profile( MLT_FILTER_SERVICE( filter ) ) );

	// Correct Width/height if necessary
	if ( *width == 0 || *height == 0 )
	{
		*width = profile->width;
		*height = profile->height;
	}

	// Assign requested width/height from our subordinate
	int owidth = *width;
	int oheight = *height;

	// Check for the special case - no aspect ratio means no problem :-)
	if ( aspect_ratio == 0.0 )
		aspect_ratio = consumer_aspect;

	// Reset the aspect ratio
	mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio );

	// XXX: This is a hack, but it forces the force_full_luma to apply by doing a RGB
	// conversion because range scaling only occurs on YUV->RGB. And we do it here,
	// after the deinterlace filter, which only operates in YUV to avoid a YUV->RGB->YUV->?.
	// Instead, it will go YUV->RGB->?.
	if ( mlt_properties_get_int( properties, "force_full_luma" ) )
		*format = mlt_image_rgb24a;

	// Hmmm...
	char *rescale = mlt_properties_get( properties, "rescale.interp" );
	if ( rescale != NULL && !strcmp( rescale, "none" ) )
		return mlt_frame_get_image( frame, image, format, width, height, writable );

	if ( mlt_properties_get_int( properties, "distort" ) == 0 )
	{
		// Normalise the input and out display aspect
		int normalised_width = profile->width;
		int normalised_height = profile->height;
		int real_width = mlt_properties_get_int( properties, "meta.media.width" );
		int real_height = mlt_properties_get_int( properties, "meta.media.height" );
		if ( real_width == 0 )
			real_width = mlt_properties_get_int( properties, "width" );
		if ( real_height == 0 )
			real_height = mlt_properties_get_int( properties, "height" );
		double input_ar = aspect_ratio * real_width / real_height;
		double output_ar = consumer_aspect * owidth / oheight;
		
// 		fprintf( stderr, "real %dx%d normalised %dx%d output %dx%d sar %f in-dar %f out-dar %f\n",
// 		real_width, real_height, normalised_width, normalised_height, owidth, oheight, aspect_ratio, input_ar, output_ar);

		// Optimised for the input_ar > output_ar case (e.g. widescreen on standard)
		int scaled_width = rint( ( input_ar * normalised_width ) / output_ar );
		int scaled_height = normalised_height;

		// Now ensure that our images fit in the output frame
		if ( scaled_width > normalised_width )
		{
			scaled_width = normalised_width;
			scaled_height = rint( ( output_ar * normalised_height ) / input_ar );
		}

		// Now calculate the actual image size that we want
		owidth = rint( scaled_width * owidth / normalised_width );
		oheight = rint( scaled_height * oheight / normalised_height );

		// Tell frame we have conformed the aspect to the consumer
		mlt_frame_set_aspect_ratio( frame, consumer_aspect );
	}

	mlt_properties_set_int( properties, "distort", 0 );

	// Now pass on the calculations down the line
	mlt_properties_set_int( properties, "resize_width", *width );
	mlt_properties_set_int( properties, "resize_height", *height );

	// If there will be padding, then we need packed image format.
	if ( *format == mlt_image_yuv420p )
	{
		int iwidth = mlt_properties_get_int( properties, "width" );
		int iheight = mlt_properties_get_int( properties, "height" );
		if ( iwidth < owidth || iheight < oheight )
			*format = mlt_image_yuv422;
	}

	// Now get the image
	if ( *format == mlt_image_yuv422 )
		owidth -= owidth % 2;
	error = mlt_frame_get_image( frame, image, format, &owidth, &oheight, writable );

	if ( error == 0 && *image )
	{
		int bpp;
		mlt_image_format_size( *format, owidth, oheight, &bpp );
		*image = frame_resize_image( frame, *width, *height, bpp );
	}

	return error;
}
예제 #5
0
파일: filter_mono.c 프로젝트: amongll/AVFX
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <framework/mlt_filter.h>
#include <string.h>
#include <framework/mlt_factory.h>
#include <framework/mlt_frame.h>
#include <framework/mlt_producer.h>
#include <framework/mlt_geometry.h>

/** Get the images and apply the luminance of the mask to the alpha of the frame.
*/

static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
	int use_alpha = mlt_deque_pop_back_int( MLT_FRAME_IMAGE_STACK( this ) );
	int midpoint = mlt_deque_pop_back_int( MLT_FRAME_IMAGE_STACK( this ) );
	int invert = mlt_deque_pop_back_int( MLT_FRAME_IMAGE_STACK( this ) );

	// Render the frame
	*format = mlt_image_yuv422;
	if ( mlt_frame_get_image( this, image, format, width, height, writable ) == 0 )
	{
		uint8_t *p = *image;
		uint8_t A = invert? 235 : 16;
		uint8_t B = invert? 16 : 235;
		int size = *width * *height;

		if ( !use_alpha )
		{
			while( size -- )