Esempio n. 1
0
File: melt.c Progetto: hrshadhin/mlt
static void on_jack_stopped( 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 )
    {
        mlt_producer_set_speed( producer, 0 );
        mlt_consumer_purge( consumer );
        mlt_producer_seek( producer, *position );
        mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 );
    }
}
Esempio n. 2
0
void MltRuntime::stop_ulk() throw (Exception)
{
	if (status == StatusRunning) {
		mlt_consumer_purge(consumer);
		mlt_consumer_stop(consumer);

		while ( mlt_consumer_is_stopped(consumer) == 0) {
			struct timespec req = {1,0};
			nanosleep(&req,NULL);
		}
		status = StatusStopped;
	}

	if (consumer) {
		mlt_consumer_close(consumer);
		consumer = NULL;
	}
}
Esempio n. 3
0
File: melt.c Progetto: 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 );
        }
    }
}
Esempio n. 4
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;
}
Esempio n. 5
0
void consumer_purge( mlt_consumer parent )
{
	consumer_sdl self = parent->child;
	if ( self->running )
		mlt_consumer_purge( self->play );
}
Esempio n. 6
0
File: melt.c Progetto: 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 );
}
Esempio n. 7
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;
}