Example #1
0
int mlt_service_detach( mlt_service self, mlt_filter filter )
{
	int error = self == NULL || filter == NULL;
	if ( error == 0 )
	{
		int i = 0;
		mlt_service_base *base = self->local;
		mlt_properties properties = MLT_SERVICE_PROPERTIES( self );

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

		if ( i < base->filter_count )
		{
			base->filters[ i ] = NULL;
			for ( i ++ ; i < base->filter_count; i ++ )
				base->filters[ i - 1 ] = base->filters[ i ];
			base->filter_count --;
			mlt_events_disconnect( MLT_FILTER_PROPERTIES( filter ), self );
			mlt_filter_close( filter );
			mlt_events_fire( properties, "service-changed", NULL );
		}
	}
	return error;
}
Example #2
0
static int consumer_play_video( consumer_sdl self, mlt_frame frame )
{
	// Get the properties of this consumer
	mlt_properties properties = self->properties;
	mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
	return 0;
}
Example #3
0
int mlt_service_move_filter( mlt_service self, int from, int to )
{
	int error = -1;
	if ( self )
	{
		mlt_service_base *base = self->local;
		if ( from < 0 ) from = 0;
		if ( from >= base->filter_count ) from = base->filter_count - 1;
		if ( to < 0 ) to = 0;
		if ( to >= base->filter_count ) to = base->filter_count - 1;
		if ( from != to && base->filter_count > 1 )
		{
			mlt_filter filter = base->filters[from];
			int i;
			if ( from > to )
			{
				for ( i = from; i > to; i-- )
					base->filters[i] = base->filters[i - 1];
			}
			else
			{
				for ( i = from; i < to; i++ )
					base->filters[i] = base->filters[i + 1];
			}
			base->filters[to] = filter;
			mlt_events_fire( MLT_SERVICE_PROPERTIES(self), "service-changed", NULL );
			error = 0;
		}
	}
	return error;
}
void Controller::seek(int position)
{
    setVolume(m_volume, false);
    if (m_producer) {
        // Always pause before seeking (if not already paused).
        if (!Settings.playerGPU())
        if (m_consumer && m_consumer->is_valid() && m_producer->get_speed() != 0) {
            // Disable real_time behavior and buffering for frame accurate seeking.
            m_consumer->set("real_time", -1);
            m_consumer->set("buffer", 0);
            m_consumer->set("prefill", 0);
        }
        m_producer->set_speed(0);
        m_producer->seek(position);
        if (m_consumer && m_consumer->is_valid()) {
            if (m_consumer->is_stopped()) {
                m_consumer->start();
            } else {
                m_consumer->purge();
                refreshConsumer(Settings.playerScrubAudio());
            }
        }
    }
    if (m_jackFilter)
        mlt_events_fire(m_jackFilter->get_properties(), "jack-seek", &position, NULL);
}
Example #5
0
void consumer_frame_show_cb( mlt_consumer sdl, mlt_consumer parent, mlt_frame frame )
{
	consumer_sdl self = parent->child;
	self->last_speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" );
	self->last_position = mlt_frame_get_position( frame );
	mlt_events_fire( MLT_CONSUMER_PROPERTIES( parent ), "consumer-frame-show", frame, NULL );
}
Example #6
0
static int consumer_play_video( consumer_sdl self, mlt_frame frame )
{
    // Get the properties of this consumer
    mlt_properties properties = self->properties;
    if ( self->running && !mlt_consumer_is_stopped( &self->parent ) )
        mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
    return 0;
}
Example #7
0
static void *consumer_thread( void *arg )
{
	// Map the argument to the object
	mlt_consumer consumer = arg;

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

	// Convenience functionality
	int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
	int terminated = 0;

	// Frame and size
	mlt_frame frame = NULL;

	// Loop while running
	while( !terminated && mlt_properties_get_int( properties, "_running" ) )
	{
		// Get the frame
		frame = mlt_consumer_rt_frame( consumer );

		// Check for termination
		if ( terminate_on_pause && frame != NULL )
			terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0;

		// Check that we have a frame to work with
		if ( frame )
		{
			avsync_stats* stats = mlt_properties_get_data( properties, "_stats", NULL );
			double fps = mlt_properties_get_double( properties, "fps" );
			mlt_position pos = mlt_frame_get_position( frame );

			 if( !strcmp( mlt_properties_get( properties, "report" ), "frame" ) )
			 {
				 stats->report_frames = 1;
			 }
			 else
			 {
				 stats->report_frames = 0;
			 }

			detect_flash( frame, pos, fps, stats );
			detect_blip( frame, pos, fps, stats );
			calculate_sync( stats );
			report_results( stats, pos );

			// Close the frame
			mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
			mlt_frame_close( frame );
		}
	}

	// Indicate that the consumer is stopped
	mlt_properties_set_int( properties, "_running", 0 );
	mlt_consumer_stopped( consumer );

	return NULL;
}
Example #8
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;
}
Example #9
0
mlt_transition mlt_factory_transition( mlt_profile profile, const char *service, const void *input )
{
	mlt_transition obj = NULL;

	// Offer the application the chance to 'create'
	mlt_events_fire( event_object, "transition-create-request", service, input, &obj, NULL );

	if ( obj == NULL )
	{
   		obj = mlt_repository_create( repository, profile, transition_type, service, input );
		mlt_events_fire( event_object, "transition-create-done", service, input, obj, NULL );
	}

	if ( obj != NULL )
	{
		mlt_properties properties = MLT_TRANSITION_PROPERTIES( obj );
		set_common_properties( properties, profile, "transition", service );
	}
	return obj;
}
Example #10
0
void Controller::seek(int position)
{
    if (m_producer) {
        m_producer->set_speed(0);
        if (m_consumer && m_consumer->is_valid())
            m_consumer->purge();
        m_producer->seek(position);
    }
    if (m_jackFilter)
        mlt_events_fire(m_jackFilter->get_properties(), "jack-seek", &position, NULL);
    refreshConsumer();
}
Example #11
0
mlt_consumer mlt_factory_consumer( mlt_profile profile, const char *service, const void *input )
{
	mlt_consumer obj = NULL;

	if ( service == NULL )
		service = mlt_environment( "MLT_CONSUMER" );

	// Offer the application the chance to 'create'
	mlt_events_fire( event_object, "consumer-create-request", service, input, &obj, NULL );

	if ( obj == NULL )
	{
		obj = mlt_repository_create( repository, profile, consumer_type, service, input );
		mlt_events_fire( event_object, "consumer-create-done", service, input, obj, NULL );
	}

	if ( obj != NULL )
	{
		mlt_properties properties = MLT_CONSUMER_PROPERTIES( obj );
		set_common_properties( properties, profile, "consumer", service );
	}
	return obj;
}
Example #12
0
static int jack_sync( jack_transport_state_t state, jack_position_t *jack_pos, void *arg )
{
	mlt_filter filter = (mlt_filter) arg;
	mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
	mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE(filter) );
	mlt_position position = mlt_profile_fps( profile ) * jack_pos->frame / jack_pos->frame_rate + 0.5;
	int result = 1;

	mlt_log_debug( MLT_FILTER_SERVICE(filter), "%s frame %u rate %u pos %d last_pos %d\n",
		JACKSTATE(state), jack_pos->frame, jack_pos->frame_rate, position,
		mlt_properties_get_position( properties, "_last_pos" ) );
	if ( state == JackTransportStopped )
	{
		mlt_events_fire( properties, "jack-stopped", &position, NULL );
		mlt_properties_set_int( properties, "_sync_guard", 0 );
	}
	else if ( state == JackTransportStarting )
	{
		result = 0;
		if ( !mlt_properties_get_int( properties, "_sync_guard" ) )
		{
			mlt_properties_set_int( properties, "_sync_guard", 1 );
			mlt_events_fire( properties, "jack-started", &position, NULL );
		}
		else if ( position >= mlt_properties_get_position( properties, "_last_pos" ) - 2 )
		{
			mlt_properties_set_int( properties, "_sync_guard", 0 );
			result = 1;
		}
	}
	else
	{
		mlt_properties_set_int( properties, "_sync_guard", 0 );
	}

	return result;
}
Example #13
0
mlt_producer mlt_factory_producer( mlt_profile profile, const char *service, const void *resource )
{
	mlt_producer obj = NULL;

	// Pick up the default normalising producer if necessary
	if ( service == NULL )
		service = mlt_environment( "MLT_PRODUCER" );

	// Offer the application the chance to 'create'
	mlt_events_fire( event_object, "producer-create-request", service, resource, &obj, NULL );

	// Try to instantiate via the specified service
	if ( obj == NULL )
	{
		obj = mlt_repository_create( repository, profile, producer_type, service, resource );
		mlt_events_fire( event_object, "producer-create-done", service, resource, obj, NULL );
		if ( obj != NULL )
		{
			mlt_properties properties = MLT_PRODUCER_PROPERTIES( obj );
			set_common_properties( properties, profile, "producer", service );
		}
	}
	return obj;
}
Example #14
0
static void *run( void *arg )
{
	// Map the argument to the object
	DeckLinkConsumer* decklink = (DeckLinkConsumer*) arg;
	mlt_consumer consumer = decklink->getConsumer();
	
	// Get the properties
	mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );

	// Convenience functionality
	int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
	int terminated = 0;

	// Frame and size
	mlt_frame frame = NULL;
	
	// Loop while running
	while ( !terminated && mlt_properties_get_int( properties, "running" ) )
	{
		// Get the frame
		frame = mlt_consumer_rt_frame( consumer );

		// Check for termination
		if ( terminate_on_pause && frame )
			terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0;

		// Check that we have a frame to work with
		if ( frame )
		{
			decklink->render( frame );
			if ( !decklink->isBuffering() )
				decklink->wait();
			
			// Close the frame
			mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
			mlt_frame_close( frame );
		}
	}

	// Indicate that the consumer is stopped
	decklink->stop();
	mlt_properties_set_int( properties, "running", 0 );
	mlt_consumer_stopped( consumer );

	return NULL;
}
Example #15
0
File: melt.c Project: hrshadhin/mlt
static void on_jack_started( mlt_properties owner, mlt_consumer consumer, mlt_position *position )
{
    mlt_producer producer = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES(consumer), "transport_producer", NULL );
    if ( producer )
    {
        if ( mlt_producer_get_speed( producer ) != 0 )
        {
            mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL );
            mlt_events_fire( jack, "jack-stop", NULL );
        }
        else
        {
            mlt_producer_set_speed( producer, 1 );
            mlt_consumer_purge( consumer );
            mlt_producer_seek( producer, *position );
            mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 );
        }
    }
}
Example #16
0
int mlt_field_plant_transition( mlt_field self, mlt_transition that, int a_track, int b_track )
{
	// Connect the transition to the last producer
	int result = mlt_transition_connect( that, self->producer, a_track, b_track );

	// If successful, then we'll use self for connecting in the future
	if ( result == 0 )
	{
		// This is now the new producer
		self->producer = MLT_TRANSITION_SERVICE( that );

		// Reconnect tractor to new producer
		mlt_tractor_connect( self->tractor, self->producer );

		// Fire an event
		mlt_events_fire( mlt_field_properties( self ), "service-changed", NULL );
	}

	return result;
}
Example #17
0
int mlt_field_plant_filter( mlt_field self, mlt_filter that, int track )
{
	// Connect the filter to the last producer
	int result = mlt_filter_connect( that, self->producer, track );

	// If successful, then we'll use this for connecting in the future
	if ( result == 0 )
	{
		// This is now the new producer
		self->producer = MLT_FILTER_SERVICE( that );

		// Reconnect tractor to new producer
		mlt_tractor_connect( self->tractor, self->producer );

		// Fire an event
		mlt_events_fire( mlt_field_properties( self ), "service-changed", NULL );
	}

	return result;
}
Example #18
0
void mlt_field_disconnect_service( mlt_field self, mlt_service service )
{
	mlt_service p = mlt_service_producer( service );
	mlt_service c = mlt_service_consumer( service);
	int i;
	switch ( mlt_service_identify(c) )
	{
		case filter_type:
			i = mlt_filter_get_track( MLT_FILTER(c) );
			mlt_service_connect_producer( c, p, i );
			break;
		case transition_type:
			i = mlt_transition_get_a_track ( MLT_TRANSITION(c) );
			mlt_service_connect_producer( c, p, i );
			MLT_TRANSITION(c)->producer = p;
			break;
		case tractor_type:
			self->producer = p;
			mlt_tractor_connect( MLT_TRACTOR(c), p );
		default:
			break;
	}
	mlt_events_fire( mlt_field_properties( self ), "service-changed", NULL );
}
Example #19
0
static int consumer_play_video( consumer_sdl self, mlt_frame frame )
{
	// Get the properties of this consumer
	mlt_properties properties = self->properties;

//	mlt_image_format vfmt = mlt_properties_get_int( properties, "mlt_image_format" );
	mlt_image_format vfmt = mlt_image_yuv422;
	int width = self->width, height = self->height;
	uint8_t *image;

	int video_off = mlt_properties_get_int( properties, "video_off" );
	int preview_off = mlt_properties_get_int( properties, "preview_off" );
	int display_off = video_off | preview_off;

	if ( self->running && !display_off )
	{
		// Get the image, width and height
		mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );

		if ( self->running )
		{
			// Determine window's new display aspect ratio
			int x = mlt_properties_get_int( properties, "window_width" );
			if ( x && x != self->window_width )
				self->window_width = x;
			x = mlt_properties_get_int( properties, "window_height" );
			if ( x && x != self->window_height )
				self->window_height = x;
			double this_aspect = ( double )self->window_width / self->window_height;

			// Get the display aspect ratio
			double display_ratio = mlt_properties_get_double( properties, "display_ratio" );

			// Determine frame's display aspect ratio
			double frame_aspect = mlt_frame_get_aspect_ratio( frame ) * width / height;

			// Store the width and height received
			self->width = width;
			self->height = height;

			// If using hardware scaler
			if ( mlt_properties_get( properties, "rescale" ) != NULL &&
				!strcmp( mlt_properties_get( properties, "rescale" ), "none" ) )
			{
				// Use hardware scaler to normalise display aspect ratio
				self->sdl_rect.w = frame_aspect / this_aspect * self->window_width;
				self->sdl_rect.h = self->window_height;
				if ( self->sdl_rect.w > self->window_width )
				{
					self->sdl_rect.w = self->window_width;
					self->sdl_rect.h = this_aspect / frame_aspect * self->window_height;
				}
			}
			// Special case optimisation to negate odd effect of sample aspect ratio
			// not corresponding exactly with image resolution.
			else if ( (int)( this_aspect * 1000 ) == (int)( display_ratio * 1000 ) ) 
			{
				self->sdl_rect.w = self->window_width;
				self->sdl_rect.h = self->window_height;
			}
			// Use hardware scaler to normalise sample aspect ratio
			else if ( self->window_height * display_ratio > self->window_width )
			{
				self->sdl_rect.w = self->window_width;
				self->sdl_rect.h = self->window_width / display_ratio;
			}
			else
			{
				self->sdl_rect.w = self->window_height * display_ratio;
				self->sdl_rect.h = self->window_height;
			}
			
			self->sdl_rect.x = ( self->window_width - self->sdl_rect.w ) / 2;
			self->sdl_rect.y = ( self->window_height - self->sdl_rect.h ) / 2;
			self->sdl_rect.x -= self->sdl_rect.x % 2;

			mlt_properties_set_int( self->properties, "rect_x", self->sdl_rect.x );
			mlt_properties_set_int( self->properties, "rect_y", self->sdl_rect.y );
			mlt_properties_set_int( self->properties, "rect_w", self->sdl_rect.w );
			mlt_properties_set_int( self->properties, "rect_h", self->sdl_rect.h );
		}

		if ( self->running && image )
		{
			unsigned char* planes[4];
			int strides[4];

			mlt_image_format_planes( vfmt, width, height, image, planes, strides );
			if ( strides[1] ) {
				SDL_UpdateYUVTexture( self->sdl_texture, NULL,
					planes[0], strides[0],
					planes[1], strides[1],
					planes[2], strides[2] );
			} else {
				SDL_UpdateTexture( self->sdl_texture, NULL, planes[0], strides[0] );
			}
			SDL_RenderClear( self->sdl_renderer );
			SDL_RenderCopy( self->sdl_renderer, self->sdl_texture, NULL, &self->sdl_rect );
			SDL_RenderPresent( self->sdl_renderer );
		}

		mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
	}
	else if ( self->running )
	{
		if ( !video_off ) {
			mlt_image_format preview_format = mlt_properties_get_int( properties, "preview_format" );
			vfmt = preview_format == mlt_image_none ? mlt_image_rgb24a : preview_format;
			mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
		}
		mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
	}

	return 0;
}
Example #20
0
static void consumer_sdl_event_cb( mlt_consumer sdl, mlt_consumer parent, SDL_Event *event )
{
	mlt_events_fire( MLT_CONSUMER_PROPERTIES( parent ), "consumer-sdl-event", event, NULL );
}
Example #21
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;
}
Example #22
0
File: melt.c Project: 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;
}
Example #23
0
static void mlt_service_filter_property_changed( mlt_service owner, mlt_service self, char *name )
{
    mlt_events_fire( MLT_SERVICE_PROPERTIES( self ), "property-changed", name, NULL );
}
Example #24
0
void mlt_consumer_stopped( mlt_consumer self )
{
	mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( self ), "running", 0 );
	mlt_events_fire( MLT_CONSUMER_PROPERTIES( self ), "consumer-stopped", NULL );
	mlt_event_unblock( self->event_listener );
}
Example #25
0
File: melt.c Project: hrshadhin/mlt
static void transport_action( mlt_producer producer, char *value )
{
    mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
    mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL );
    mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL );
    mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL );
    mlt_position position = producer? mlt_producer_position( producer ) : 0;

    mlt_properties_set_int( properties, "stats_off", 1 );

    if ( strlen( value ) == 1 )
    {
        switch( value[ 0 ] )
        {
        case 'q':
        case 'Q':
            mlt_properties_set_int( properties, "done", 1 );
            mlt_events_fire( jack, "jack-stop", NULL );
            break;
        case '0':
            position = 0;
            mlt_producer_set_speed( producer, 1 );
            mlt_producer_seek( producer, position );
            mlt_consumer_purge( consumer );
            mlt_events_fire( jack, "jack-seek", &position, NULL );
            break;
        case '1':
            mlt_producer_set_speed( producer, -10 );
            break;
        case '2':
            mlt_producer_set_speed( producer, -5 );
            break;
        case '3':
            mlt_producer_set_speed( producer, -2 );
            break;
        case '4':
            mlt_producer_set_speed( producer, -1 );
            break;
        case '5':
            mlt_producer_set_speed( producer, 0 );
            mlt_consumer_purge( consumer );
            mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 );
            mlt_events_fire( jack, "jack-stop", NULL );
            break;
        case '6':
        case ' ':
            if ( !jack || mlt_producer_get_speed( producer ) != 0 )
                mlt_producer_set_speed( producer, 1 );
            mlt_consumer_purge( consumer );
            mlt_events_fire( jack, "jack-start", NULL );
            break;
        case '7':
            mlt_producer_set_speed( producer, 2 );
            break;
        case '8':
            mlt_producer_set_speed( producer, 5 );
            break;
        case '9':
            mlt_producer_set_speed( producer, 10 );
            break;
        case 'd':
            if ( multitrack != NULL )
            {
                int i = 0;
                mlt_position last = -1;
                fprintf( stderr, "\n" );
                for ( i = 0; 1; i ++ )
                {
                    position = mlt_multitrack_clip( multitrack, mlt_whence_relative_start, i );
                    if ( position == last )
                        break;
                    last = position;
                    fprintf( stderr, "%d: %d\n", i, (int)position );
                }
            }
            break;

        case 'g':
            if ( multitrack != NULL )
            {
                position = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 );
                mlt_producer_seek( producer, position );
                mlt_consumer_purge( consumer );
                mlt_events_fire( jack, "jack-seek", &position, NULL );
            }
            break;
        case 'H':
            if ( producer != NULL )
            {
                position -= mlt_producer_get_fps( producer ) * 60;
                mlt_consumer_purge( consumer );
                mlt_producer_seek( producer, position );
                mlt_events_fire( jack, "jack-seek", &position, NULL );
            }
            break;
        case 'h':
            if ( producer != NULL )
            {
                position--;
                mlt_producer_set_speed( producer, 0 );
                mlt_consumer_purge( consumer );
                mlt_producer_seek( producer, position );
                mlt_events_fire( jack, "jack-stop", NULL );
                mlt_events_fire( jack, "jack-seek", &position, NULL );
            }
            break;
        case 'j':
            if ( multitrack != NULL )
            {
                position = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 );
                mlt_consumer_purge( consumer );
                mlt_producer_seek( producer, position );
                mlt_events_fire( jack, "jack-seek", &position, NULL );
            }
            break;
        case 'k':
            if ( multitrack != NULL )
            {
                position = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 );
                mlt_consumer_purge( consumer );
                mlt_producer_seek( producer, position );
                mlt_events_fire( jack, "jack-seek", &position, NULL );
            }
            break;
        case 'l':
            if ( producer != NULL )
            {
                position++;
                mlt_consumer_purge( consumer );
                if ( mlt_producer_get_speed( producer ) != 0 )
                {
                    mlt_producer_set_speed( producer, 0 );
                    mlt_events_fire( jack, "jack-stop", NULL );
                }
                else
                {
                    mlt_producer_seek( producer, position );
                    mlt_events_fire( jack, "jack-seek", &position, NULL );
                }
            }
            break;
        case 'L':
            if ( producer != NULL )
            {
                position += mlt_producer_get_fps( producer ) * 60;
                mlt_consumer_purge( consumer );
                mlt_producer_seek( producer, position );
                mlt_events_fire( jack, "jack-seek", &position, NULL );
            }
            break;
        }

        mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 );
    }

    mlt_properties_set_int( properties, "stats_off", 0 );
}
Example #26
0
static void mlt_producer_service_changed( mlt_service owner, mlt_producer self )
{
	mlt_events_fire( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( self ) ), "producer-changed", NULL );
}
Example #27
0
static void mlt_producer_property_changed( mlt_service owner, mlt_producer self, char *name )
{
	if ( !strcmp( name, "in" ) || !strcmp( name, "out" ) || !strcmp( name, "length" ) )
		mlt_events_fire( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( self ) ), "producer-changed", NULL );
}
Example #28
0
static void *consumer_read_ahead_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" );

	// 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" );

	// Get the audio settings
	mlt_audio_format afmt = mlt_audio_s16;
	const char *format = mlt_properties_get( properties, "mlt_audio_format" );
	if ( format )
	{
		if ( !strcmp( format, "none" ) )
			afmt = mlt_audio_none;
		else if ( !strcmp( format, "s32" ) )
			afmt = mlt_audio_s32;
		else if ( !strcmp( format, "s32le" ) )
			afmt = mlt_audio_s32le;
		else if ( !strcmp( format, "float" ) )
			afmt = mlt_audio_float;
		else if ( !strcmp( format, "f32le" ) )
			afmt = mlt_audio_f32le;
		else if ( !strcmp( format, "u8" ) )
			afmt = mlt_audio_u8;
	}
	int counter = 0;
	double fps = mlt_properties_get_double( properties, "fps" );
	int channels = mlt_properties_get_int( properties, "channels" );
	int frequency = mlt_properties_get_int( properties, "frequency" );
	int samples = 0;
	void *audio = NULL;

	// See if audio is turned off
	int audio_off = mlt_properties_get_int( properties, "audio_off" );

	// Get the maximum size of the buffer
	int buffer = mlt_properties_get_int( properties, "buffer" ) + 1;

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

	// Time structures
	struct timeval ante;

	// Average time for get_frame and get_image
	int count = 0;
	int skipped = 0;
	int64_t time_process = 0;
	int skip_next = 0;
	mlt_position pos = 0;
	mlt_position start_pos = 0;
	mlt_position last_pos = 0;
	int frame_duration = mlt_properties_get_int( properties, "frame_duration" );
	int drop_max = mlt_properties_get_int( properties, "drop_max" );

	if ( preview_off && preview_format != 0 )
		self->format = preview_format;

	// Get the first frame
	frame = mlt_consumer_get_frame( self );

	if ( frame )
	{
		// Get the image of the first frame
		if ( !video_off )
		{
			mlt_events_fire( MLT_CONSUMER_PROPERTIES( self ), "consumer-frame-render", frame, NULL );
			mlt_frame_get_image( frame, &image, &self->format, &width, &height, 0 );
		}

		if ( !audio_off )
		{
			samples = mlt_sample_calculator( fps, frequency, counter++ );
			mlt_frame_get_audio( frame, &audio, &afmt, &frequency, &channels, &samples );
		}

		// Mark as rendered
		mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 1 );
		last_pos = start_pos = pos = mlt_frame_get_position( frame );
	}

	// Get the starting time (can ignore the times above)
	gettimeofday( &ante, NULL );

	// Continue to read ahead
	while ( self->ahead )
	{
		// Put the current frame into the queue
		pthread_mutex_lock( &self->queue_mutex );
		while( self->ahead && mlt_deque_count( self->queue ) >= buffer )
			pthread_cond_wait( &self->queue_cond, &self->queue_mutex );
		mlt_deque_push_back( self->queue, frame );
		pthread_cond_broadcast( &self->queue_cond );
		pthread_mutex_unlock( &self->queue_mutex );

		// Get the next frame
		frame = mlt_consumer_get_frame( self );

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

		// Increment the counter used for averaging processing cost
		count ++;

		// All non-normal playback frames should be shown
		if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "_speed" ) != 1 )
		{
#ifdef DEINTERLACE_ON_NOT_NORMAL_SPEED
			mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "consumer_deinterlace", 1 );
#endif
			// Indicate seeking or trick-play
			start_pos = pos;
		}

		// If skip flag not set or frame-dropping disabled
		if ( !skip_next || self->real_time == -1 )
		{
			if ( !video_off )
			{
				// Reset width/height - could have been changed by previous mlt_frame_get_image
				width = mlt_properties_get_int( properties, "width" );
				height = mlt_properties_get_int( properties, "height" );

				// Get the image
				mlt_events_fire( MLT_CONSUMER_PROPERTIES( self ), "consumer-frame-render", frame, NULL );
				mlt_frame_get_image( frame, &image, &self->format, &width, &height, 0 );
			}

			// Indicate the rendered image is available.
			mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 1 );

			// Reset consecutively-skipped counter
			skipped = 0;
		}
		else // Skip image processing
		{
			// Increment the number of consecutively-skipped frames
			skipped++;

			// If too many (1 sec) consecutively-skipped frames
			if ( skipped > drop_max )
			{
				// Reset cost tracker
				time_process = 0;
				count = 1;
				mlt_log_verbose( self, "too many frames dropped - forcing next frame\n" );
			}
		}

		// Always process audio
		if ( !audio_off )
		{
			samples = mlt_sample_calculator( fps, frequency, counter++ );
			mlt_frame_get_audio( frame, &audio, &afmt, &frequency, &channels, &samples );
		}

		// Get the time to process this frame
		int64_t time_current = time_difference( &ante );

		// If the current time is not suddenly some large amount
		if ( time_current < time_process / count * 20 || !time_process || count < 5 )
		{
			// Accumulate the cost for processing this frame
			time_process += time_current;
		}
		else
		{
			mlt_log_debug( self, "current %"PRId64" threshold %"PRId64" count %d\n",
				time_current, (int64_t) (time_process / count * 20), count );
			// Ignore the cost of this frame's time
			count--;
		}

		// Determine if we started, resumed, or seeked
		if ( pos != last_pos + 1 )
			start_pos = pos;
		last_pos = pos;

		// Do not skip the first 20% of buffer at start, resume, or seek
		if ( pos - start_pos <= buffer / 5 + 1 )
		{
			// Reset cost tracker
			time_process = 0;
			count = 1;
		}

		// Reset skip flag
		skip_next = 0;

		// Only consider skipping if the buffer level is low (or really small)
		if ( mlt_deque_count( self->queue ) <= buffer / 5 + 1 )
		{
			// Skip next frame if average cost exceeds frame duration.
			if ( time_process / count > frame_duration )
				skip_next = 1;
			if ( skip_next )
				mlt_log_debug( self, "avg usec %"PRId64" (%"PRId64"/%d) duration %d\n",
					time_process/count, time_process, count, frame_duration);
		}
	}

	// Remove the last frame
	mlt_frame_close( frame );

	return NULL;
}
Example #29
0
static void on_frame_show( void *dummy, mlt_properties properties, mlt_frame frame )
{
    mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
}
Example #30
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;
}