示例#1
0
文件: mlt_tractor.c 项目: elfring/mlt
void mlt_tractor_refresh( mlt_tractor self )
{
	mlt_multitrack multitrack = mlt_tractor_multitrack( self );
	mlt_properties multitrack_props = MLT_MULTITRACK_PROPERTIES( multitrack );
	mlt_properties properties = MLT_TRACTOR_PROPERTIES( self );
	mlt_events_block( multitrack_props, properties );
	mlt_events_block( properties, properties );
	mlt_multitrack_refresh( multitrack );
	mlt_properties_set_position( properties, "in", 0 );
	mlt_properties_set_position( properties, "out", mlt_properties_get_position( multitrack_props, "out" ) );
	mlt_events_unblock( properties, properties );
	mlt_events_unblock( multitrack_props, properties );
	mlt_properties_set_position( properties, "length", mlt_properties_get_position( multitrack_props, "length" ) );
}
示例#2
0
int mlt_producer_set_in_and_out( mlt_producer self, mlt_position in, mlt_position out )
{
	mlt_properties properties = MLT_PRODUCER_PROPERTIES( self );

	// Correct ins and outs if necessary
	if ( in < 0 )
		in = 0;
	else if ( in >= mlt_producer_get_length( self ) )
		in = mlt_producer_get_length( self ) - 1;

	if ( ( out < 0 || out >= mlt_producer_get_length( self ) ) && !mlt_producer_is_blank( self ) )
		out = mlt_producer_get_length( self ) - 1;
	else if ( ( out < 0 || out >= mlt_producer_get_length( self ) ) && mlt_producer_is_blank( self ) )
		mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( self ), "length", out + 1 );
	else if ( out < 0 )
		out = 0;

	// Swap ins and outs if wrong
	if ( out < in )
	{
		mlt_position t = in;
		in = out;
		out = t;
	}

	// Set the values
	mlt_events_block( properties, properties );
	mlt_properties_set_position( properties, "in", in );
	mlt_events_unblock( properties, properties );
	mlt_properties_set_position( properties, "out", out );

	return 0;
}
示例#3
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;
}
示例#4
0
void mlt_service_close( mlt_service self )
{
	if ( self != NULL && mlt_properties_dec_ref( MLT_SERVICE_PROPERTIES( self ) ) <= 0 )
	{
		if ( self->close != NULL )
		{
			self->close( self->close_object );
		}
		else
		{
			mlt_service_base *base = self->local;
			int i = 0;
			int count = base->filter_count;
			mlt_events_block( MLT_SERVICE_PROPERTIES( self ), self );
			while( count -- )
				mlt_service_detach( self, base->filters[ 0 ] );
			free( base->filters );
			for ( i = 0; i < base->count; i ++ )
				if ( base->in[ i ] != NULL )
					mlt_service_close( base->in[ i ] );
			self->parent.close = NULL;
			free( base->in );
			pthread_mutex_destroy( &base->mutex );
			free( base );
			mlt_properties_close( &self->parent );
		}
	}
}
示例#5
0
int mlt_producer_clear( mlt_producer self )
{
	if ( self != NULL )
	{
		mlt_properties properties = MLT_PRODUCER_PROPERTIES( self );
		mlt_events_block( properties, properties );
		mlt_properties_set_position( properties, "in", 0 );
		mlt_events_unblock( properties, properties );
		mlt_properties_set_position( properties, "out", -1 );
	}
	return 0;
}
示例#6
0
static mlt_producer mlt_producer_clone( mlt_producer self )
{
	mlt_producer clone = NULL;
	mlt_properties properties = MLT_PRODUCER_PROPERTIES( self );
	char *resource = mlt_properties_get( properties, "resource" );
	char *service = mlt_properties_get( properties, "mlt_service" );
	mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( self ) );

	mlt_events_block( mlt_factory_event_object( ), mlt_factory_event_object( ) );

	if ( service != NULL )
		clone = mlt_factory_producer( profile, service, resource );

	if ( clone == NULL && resource != NULL )
		clone = mlt_factory_producer( profile, NULL, resource );

	if ( clone != NULL )
		mlt_properties_inherit( MLT_PRODUCER_PROPERTIES( clone ), properties );

	mlt_events_unblock( mlt_factory_event_object( ), mlt_factory_event_object( ) );

	return clone;
}
示例#7
0
void mlt_multitrack_refresh( mlt_multitrack self )
{
	int i = 0;

	// Obtain the properties of this multitrack
	mlt_properties properties = MLT_MULTITRACK_PROPERTIES( self );

	// We need to ensure that the multitrack reports the longest track as its length
	mlt_position length = 0;

	// Obtain stats on all connected services
	for ( i = 0; i < self->count; i ++ )
	{
		// Get the producer from this index
		mlt_track track = self->list[ i ];
		mlt_producer producer = track->producer;

		// If it's allocated then, update our stats
		if ( producer != NULL )
		{
			// If we have more than 1 track, we must be in continue mode
			if ( self->count > 1 )
				mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ), "eof", "continue" );

			// Determine the longest length
			//if ( !mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( producer ), "hide" ) )
				length = mlt_producer_get_playtime( producer ) > length ? mlt_producer_get_playtime( producer ) : length;
		}
	}

	// Update multitrack properties now - we'll not destroy the in point here
	mlt_events_block( properties, properties );
	mlt_properties_set_position( properties, "length", length );
	mlt_events_unblock( properties, properties );
	mlt_properties_set_position( properties, "out", length - 1 );
}
示例#8
0
static void check_for_reset( mlt_filter filter, int channels, int frequency )
{
	mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
	private_data* pdata = (private_data*)filter->child;

	if( pdata->reset )
	{
		if( pdata->r128 )
		{
			ebur128_destroy( &pdata->r128 );
		}
		pdata->r128 = 0;
		pdata->reset = 0;
		pdata->prev_pos = -1;
		mlt_events_block( properties, filter );
		mlt_properties_set( properties, "frames_processed", "0" );
		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_int( properties, "reset_count", mlt_properties_get_int( properties, "reset_count") + 1 );
		mlt_properties_set_int( properties, "reset", 0 );
		mlt_events_unblock( properties, filter );
	}

	if( !pdata->r128 )
	{
		int mode = EBUR128_MODE_HISTOGRAM;

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_program" ) )
		{
			mode |= EBUR128_MODE_I;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_shortterm" ) )
		{
			mode |= EBUR128_MODE_S;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_momentary" ) )
		{
			mode |= EBUR128_MODE_M;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_range" ) )
		{
			mode |= EBUR128_MODE_LRA;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_peak" ) )
		{
			mode |= EBUR128_MODE_SAMPLE_PEAK;
		}

		if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "calc_true_peak" ) )
		{
			mode |= EBUR128_MODE_TRUE_PEAK;
		}

		pdata->r128 = ebur128_init( channels, frequency,  mode );
	}
}
示例#9
0
int refresh_qimage( producer_qimage self, mlt_frame frame )
{
	// Obtain properties of frame and producer
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
	mlt_producer producer = &self->parent;
	mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );

	// Check if user wants us to reload the image
	if ( mlt_properties_get_int( producer_props, "force_reload" ) )
	{
		self->qimage = NULL;
		self->current_image = NULL;
		mlt_properties_set_int( producer_props, "force_reload", 0 );
	}

	// Get the time to live for each frame
	double ttl = mlt_properties_get_int( producer_props, "ttl" );

	// Get the original position of this frame
	mlt_position position = mlt_frame_original_position( frame );
	position += mlt_producer_get_in( producer );

	// Image index
	int image_idx = ( int )floor( ( double )position / ttl ) % self->count;

	// Key for the cache
	char image_key[ 10 ];
	sprintf( image_key, "%d", image_idx );

	int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );
	
	
	if ( app == NULL ) 
	{
		if ( qApp ) 
		{
			app = qApp;
		}
		else 
		{
#ifdef linux
			if ( getenv("DISPLAY") == 0 )
			{
				mlt_log_panic( MLT_PRODUCER_SERVICE( producer ), "Error, cannot render titles without an X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" );
				return -1;
			}
#endif
			int argc = 1;
			char* argv[1];
			argv[0] = (char*) "xxx";
			app = new QApplication( argc, argv );
			const char *localename = mlt_properties_get_lcnumeric( MLT_SERVICE_PROPERTIES( MLT_PRODUCER_SERVICE( producer ) ) );
			QLocale::setDefault( QLocale( localename ) );
		}
	}

	if ( image_idx != self->qimage_idx )
		self->qimage = NULL;
	if ( !self->qimage || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif )
	{
		self->current_image = NULL;
		QImage *qimage = new QImage( QString::fromUtf8( mlt_properties_get_value( self->filenames, image_idx ) ) );
		self->qimage = qimage;

		if ( !qimage->isNull( ) )
		{
			// Read the exif value for this file
			if ( !disable_exif )
				qimage = reorient_with_exif( self, image_idx, qimage );

			// Register qimage for destruction and reuse
			mlt_cache_item_close( self->qimage_cache );
			mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage", qimage, 0, ( mlt_destructor )qimage_delete );
			self->qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
			self->qimage_idx = image_idx;

			// Store the width/height of the qimage
			self->current_width = qimage->width( );
			self->current_height = qimage->height( );

			mlt_events_block( producer_props, NULL );
			mlt_properties_set_int( producer_props, "meta.media.width", self->current_width );
			mlt_properties_set_int( producer_props, "meta.media.height", self->current_height );
			mlt_properties_set_int( producer_props, "_disable_exif", disable_exif );
			mlt_events_unblock( producer_props, NULL );
		}
		else
		{
			delete qimage;
			self->qimage = NULL;
		}
	}

	// Set width/height of frame
	mlt_properties_set_int( properties, "width", self->current_width );
	mlt_properties_set_int( properties, "height", self->current_height );

	return image_idx;
}
示例#10
0
static void *consumer_thread( void *arg )
{
	// Identify the arg
	consumer_sdl self = arg;

	// Get the consumer
	mlt_consumer consumer = &self->parent;

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

	// internal intialization
	mlt_frame frame = NULL;
	int last_position = -1;
	int eos = 0;
	int eos_threshold = 20;
	if ( self->play )
		eos_threshold = eos_threshold + mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( self->play ), "buffer" );

	// Determine if the application is dealing with the preview
	int preview_off = mlt_properties_get_int( properties, "preview_off" );

	pthread_mutex_lock( &self->refresh_mutex );
	self->refresh_count = 0;
	pthread_mutex_unlock( &self->refresh_mutex );

	// Loop until told not to
	while( self->running )
	{
		// Get a frame from the attached producer
		frame = mlt_consumer_get_frame( consumer );

		// Ensure that we have a frame
		if ( self->running && frame != NULL )
		{
			// Get the speed of the frame
			double speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" );

			// Lock during the operation
			mlt_service_lock( MLT_CONSUMER_SERVICE( consumer ) );

			// Get refresh request for the current frame
			int refresh = mlt_properties_get_int( properties, "refresh" );

			// Decrement refresh and clear changed
			mlt_events_block( properties, properties );
			mlt_properties_set_int( properties, "refresh", 0 );
			mlt_events_unblock( properties, properties );

			// Unlock after the operation
			mlt_service_unlock( MLT_CONSUMER_SERVICE( consumer ) );

			// Set the changed property on this frame for the benefit of still
			mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "refresh", refresh );

			// Make sure the recipient knows that this frame isn't really rendered
			mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 0 );

			// Optimisation to reduce latency
			if ( speed == 1.0 )
			{
				if ( last_position != -1 && last_position + 1 != mlt_frame_get_position( frame ) )
					mlt_consumer_purge( self->play );
				last_position = mlt_frame_get_position( frame );
			}
			else
			{
				//mlt_consumer_purge( self->play );
				last_position = -1;
			}

			// If we aren't playing normally, then use the still
			if ( speed != 1 )
			{
				mlt_producer producer = MLT_PRODUCER( mlt_service_get_producer( MLT_CONSUMER_SERVICE( consumer ) ) );
				mlt_position duration = producer? mlt_producer_get_playtime( producer ) : -1;
				int pause = 0;

#ifndef SKIP_WAIT_EOS
				if ( self->active == self->play )
				{
					// Do not interrupt the play consumer near the end
					if ( duration - self->last_position > eos_threshold )
					{
						// Get a new frame at the sought position
						mlt_frame_close( frame );
						if ( producer )
							mlt_producer_seek( producer, self->last_position );
						frame = mlt_consumer_get_frame( consumer );
						pause = 1;
					}
					else
					{
						// Send frame with speed 0 to stop it
						if ( frame && !mlt_consumer_is_stopped( self->play ) )
						{
							mlt_consumer_put_frame( self->play, frame );
							frame = NULL;
							eos = 1;
						}

						// Check for end of stream
						if ( mlt_consumer_is_stopped( self->play ) )
						{
							// Stream has ended
							mlt_log_verbose( MLT_CONSUMER_SERVICE( consumer ), "END OF STREAM\n" );
							pause = 1;
							eos = 0; // reset eos indicator
						}
						else
						{
							// Prevent a tight busy loop
							struct timespec tm = { 0, 100000L }; // 100 usec
							nanosleep( &tm, NULL );
						}
					}
				}
#else
				pause = self->active == self->play;
#endif
				if ( pause )
				{
					// Start the still consumer
					if ( !mlt_consumer_is_stopped( self->play ) )
						mlt_consumer_stop( self->play );
					self->last_speed = speed;
					self->active = self->still;
					self->ignore_change = 0;
					mlt_consumer_start( self->still );
				}
				// Send the frame to the active child
				if ( frame && !eos )
				{
					mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "refresh", 1 );
					if ( self->active )
						mlt_consumer_put_frame( self->active, frame );
				}
				if ( pause && speed == 0.0 )
				{
					mlt_events_fire( properties, "consumer-sdl-paused", NULL );
				}
			}
			// Allow a little grace time before switching consumers on speed changes
			else if ( self->ignore_change -- > 0 && self->active != NULL && !mlt_consumer_is_stopped( self->active ) )
			{
				mlt_consumer_put_frame( self->active, frame );
			}
			// Otherwise use the normal player
			else
			{
				if ( !mlt_consumer_is_stopped( self->still ) )
					mlt_consumer_stop( self->still );
				if ( mlt_consumer_is_stopped( self->play ) )
				{
					self->last_speed = speed;
					self->active = self->play;
					self->ignore_change = 0;
					mlt_consumer_start( self->play );
				}
				if ( self->play )
					mlt_consumer_put_frame( self->play, frame );
			}

			// Copy the rectangle info from the active consumer
			if ( self->running && preview_off == 0 && self->active )
			{
				mlt_properties active = MLT_CONSUMER_PROPERTIES( self->active );
				mlt_service_lock( MLT_CONSUMER_SERVICE( consumer ) );
				mlt_properties_set_int( properties, "rect_x", mlt_properties_get_int( active, "rect_x" ) );
				mlt_properties_set_int( properties, "rect_y", mlt_properties_get_int( active, "rect_y" ) );
				mlt_properties_set_int( properties, "rect_w", mlt_properties_get_int( active, "rect_w" ) );
				mlt_properties_set_int( properties, "rect_h", mlt_properties_get_int( active, "rect_h" ) );
				mlt_service_unlock( MLT_CONSUMER_SERVICE( consumer ) );
			}

			if ( self->active == self->still )
			{
				pthread_mutex_lock( &self->refresh_mutex );
				if ( self->running && speed == 0 && self->refresh_count <= 0 )
				{
					mlt_events_fire( properties, "consumer-sdl-paused", NULL );
					pthread_cond_wait( &self->refresh_cond, &self->refresh_mutex );
				}
				self->refresh_count --;
				pthread_mutex_unlock( &self->refresh_mutex );
			}
		}
		else
		{
			if ( frame ) mlt_frame_close( frame );
			mlt_consumer_put_frame( self->active, NULL );
			self->running = 0;
		}
	}

	if ( self->play ) mlt_consumer_stop( self->play );
	if ( self->still ) mlt_consumer_stop( self->still );

	return NULL;
}
示例#11
0
static void *consumer_thread( void *arg )
{
	// Identify the arg
	consumer_sdl self = arg;

	// Get the consumer
	mlt_consumer consumer = &self->parent;

	// Get the properties
	mlt_properties consumer_props = MLT_CONSUMER_PROPERTIES( consumer );

	// Video thread
	pthread_t thread;

	// internal intialization
	int init_audio = 1;
	int init_video = 1;
	mlt_frame frame = NULL;
	mlt_properties properties = NULL;
	int duration = 0;
	int64_t playtime = 0;
	struct timespec tm = { 0, 100000 };
//	int last_position = -1;

	pthread_mutex_lock( &self->refresh_mutex );
	self->refresh_count = 0;
	pthread_mutex_unlock( &self->refresh_mutex );

	// Loop until told not to
	while( self->running )
	{
		// Get a frame from the attached producer
		frame = mlt_consumer_rt_frame( consumer );

		// Ensure that we have a frame
		if ( frame )
		{
			// Get the frame properties
			properties =  MLT_FRAME_PROPERTIES( frame );

			// Get the speed of the frame
			double speed = mlt_properties_get_double( properties, "_speed" );

			// Clear refresh
			mlt_events_block( consumer_props, consumer_props );
			mlt_properties_set_int( consumer_props, "refresh", 0 );
			mlt_events_unblock( consumer_props, consumer_props );

			// Play audio
			init_audio = consumer_play_audio( self, frame, init_audio, &duration );

			// Determine the start time now
			if ( self->playing && init_video )
			{
				// Create the video thread
				pthread_create( &thread, NULL, video_thread, self );

				// Video doesn't need to be initialised any more
				init_video = 0;
			}

			// Set playtime for this frame
			mlt_properties_set_int( properties, "playtime", playtime );

			while ( self->running && speed != 0 && mlt_deque_count( self->queue ) > 15 )
				nanosleep( &tm, NULL );

			// Push this frame to the back of the queue
			if ( self->running && speed )
			{
				pthread_mutex_lock( &self->video_mutex );
				if ( self->is_purge && speed == 1.0 )
				{
					mlt_frame_close( frame );
					frame = NULL;
					self->is_purge = 0;
				}
				else
				{
					mlt_deque_push_back( self->queue, frame );
					pthread_cond_broadcast( &self->video_cond );
				}
				pthread_mutex_unlock( &self->video_mutex );

				// Calculate the next playtime
				playtime += ( duration * 1000 );
			}
			else if ( self->running )
			{
				pthread_mutex_lock( &self->refresh_mutex );
				consumer_play_video( self, frame );
				mlt_frame_close( frame );
				frame = NULL;
				self->refresh_count --;
				if ( self->refresh_count <= 0 )
				{
					pthread_cond_wait( &self->refresh_cond, &self->refresh_mutex );
				}
				pthread_mutex_unlock( &self->refresh_mutex );
			}

			// Optimisation to reduce latency
			if ( speed == 1.0 )
			{
                // TODO: disabled due to misbehavior on parallel-consumer
//				if ( last_position != -1 && last_position + 1 != mlt_frame_get_position( frame ) )
//					mlt_consumer_purge( consumer );
//				last_position = mlt_frame_get_position( frame );
			}
			else
			{
				mlt_consumer_purge( consumer );
//				last_position = -1;
			}
		}
	}

	// Kill the video thread
	if ( init_video == 0 )
	{
		pthread_mutex_lock( &self->video_mutex );
		pthread_cond_broadcast( &self->video_cond );
		pthread_mutex_unlock( &self->video_mutex );
		pthread_join( thread, NULL );
	}

	if ( frame )
	{
		// The video thread has cleared out the queue. But the audio was played
		// for this frame. So play the video before stopping so the display has
		// the option to catch up with the audio.
		consumer_play_video( self, frame );
		mlt_frame_close( frame );
		frame = NULL;
	}

	self->audio_avail = 0;

	return NULL;
}
示例#12
0
int refresh_qimage( producer_qimage self, mlt_frame frame )
{
	// Obtain properties of frame and producer
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
	mlt_producer producer = &self->parent;
	mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );

	// Check if user wants us to reload the image
	if ( mlt_properties_get_int( producer_props, "force_reload" ) )
	{
		self->qimage = NULL;
		self->current_image = NULL;
		mlt_properties_set_int( producer_props, "force_reload", 0 );
	}

	// Get the time to live for each frame
	double ttl = mlt_properties_get_int( producer_props, "ttl" );

	// Get the original position of this frame
	mlt_position position = mlt_frame_original_position( frame );
	position += mlt_producer_get_in( producer );

	// Image index
	int image_idx = ( int )floor( ( double )position / ttl ) % self->count;

	int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );

	if ( !createQApplicationIfNeeded( MLT_PRODUCER_SERVICE(producer) ) )
		return -1;

	if ( image_idx != self->qimage_idx )
		self->qimage = NULL;
	if ( !self->qimage || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif )
	{
		self->current_image = NULL;
		QImage *qimage = new QImage( QString::fromUtf8( mlt_properties_get_value( self->filenames, image_idx ) ) );
		self->qimage = qimage;

		if ( !qimage->isNull( ) )
		{
			// Read the exif value for this file
			if ( !disable_exif )
				qimage = reorient_with_exif( self, image_idx, qimage );

			// Register qimage for destruction and reuse
			mlt_cache_item_close( self->qimage_cache );
			mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage", qimage, 0, ( mlt_destructor )qimage_delete );
			self->qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
			self->qimage_idx = image_idx;

			// Store the width/height of the qimage
			self->current_width = qimage->width( );
			self->current_height = qimage->height( );

			mlt_events_block( producer_props, NULL );
			mlt_properties_set_int( producer_props, "meta.media.width", self->current_width );
			mlt_properties_set_int( producer_props, "meta.media.height", self->current_height );
			mlt_properties_set_int( producer_props, "_disable_exif", disable_exif );
			mlt_events_unblock( producer_props, NULL );
		}
		else
		{
			delete qimage;
			self->qimage = NULL;
		}
	}

	// Set width/height of frame
	mlt_properties_set_int( properties, "width", self->current_width );
	mlt_properties_set_int( properties, "height", self->current_height );

	return image_idx;
}
示例#13
0
static int refresh_pixbuf( producer_pixbuf self, mlt_frame frame )
{
	// Obtain properties of frame and producer
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
	mlt_producer producer = &self->parent;
	mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );

	// Check if user wants us to reload the image
	if ( mlt_properties_get_int( producer_props, "force_reload" ) )
	{
		self->pixbuf = NULL;
		self->image = NULL;
		mlt_properties_set_int( producer_props, "force_reload", 0 );
	}

	// Get the time to live for each frame
	double ttl = mlt_properties_get_int( producer_props, "ttl" );

	// Get the original position of this frame
	mlt_position position = mlt_frame_original_position( frame );
	position += mlt_producer_get_in( producer );

	// Image index
	int loop = mlt_properties_get_int( producer_props, "loop" );
	int current_idx;
	if (loop) {
		current_idx = ( int )floor( ( double )position / ttl ) % self->count;
	} else {
		current_idx = MIN(( double )position / ttl, self->count - 1);
	}

	// Key for the cache
	char image_key[ 10 ];
	sprintf( image_key, "%d", current_idx );

	int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );

	if ( current_idx != self->pixbuf_idx )
		self->pixbuf = NULL;
	if ( !self->pixbuf || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif )
	{
		GError *error = NULL;

		self->image = NULL;
		pthread_mutex_lock( &g_mutex );
		self->pixbuf = gdk_pixbuf_new_from_file( mlt_properties_get_value( self->filenames, current_idx ), &error );
		if ( self->pixbuf )
		{
			// Read the exif value for this file
			if ( !disable_exif )
				self->pixbuf = reorient_with_exif( self, current_idx, self->pixbuf );

			// Register this pixbuf for destruction and reuse
			mlt_cache_item_close( self->pixbuf_cache );
			mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf", self->pixbuf, 0, ( mlt_destructor )g_object_unref );
			self->pixbuf_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf" );
			self->pixbuf_idx = current_idx;

			// Store the width/height of the pixbuf temporarily
			self->width = gdk_pixbuf_get_width( self->pixbuf );
			self->height = gdk_pixbuf_get_height( self->pixbuf );

			mlt_events_block( producer_props, NULL );
			mlt_properties_set_int( producer_props, "meta.media.width", self->width );
			mlt_properties_set_int( producer_props, "meta.media.height", self->height );
			mlt_properties_set_int( producer_props, "_disable_exif", disable_exif );
			mlt_events_unblock( producer_props, NULL );

		}
		pthread_mutex_unlock( &g_mutex );
	}

	// Set width/height of frame
	mlt_properties_set_int( properties, "width", self->width );
	mlt_properties_set_int( properties, "height", self->height );

	return current_idx;
}