Exemple #1
0
	int op(int op_id, int arg)
	{
		int r;

		// lock operation mutex
		pthread_mutex_lock(&m_op_lock);

		mlt_log_debug( getConsumer(), "%s: op_id=%d\n", __FUNCTION__, op_id );

		// notify op id
		pthread_mutex_lock(&m_op_arg_mutex);
		m_op_id = op_id;
		m_op_arg = arg;
		pthread_cond_signal(&m_op_arg_cond);
		pthread_mutex_unlock(&m_op_arg_mutex);

		// wait op done
		pthread_mutex_lock(&m_op_arg_mutex);
		while(OP_NONE != m_op_id)
			pthread_cond_wait(&m_op_arg_cond, &m_op_arg_mutex);
		pthread_mutex_unlock(&m_op_arg_mutex);

		// save result
		r = m_op_res;

		mlt_log_debug( getConsumer(), "%s: r=%d\n", __FUNCTION__, r );

		// unlock operation mutex
		pthread_mutex_unlock(&m_op_lock);

		return r;
	}
	void createFrame()
	{
		m_videoFrame = 0;
		// Generate a DeckLink video frame
		if ( S_OK != m_deckLinkOutput->CreateVideoFrame( m_width, m_height,
			m_width * 2, bmdFormat8BitYUV, bmdFrameFlagDefault, &m_videoFrame ) )
		{
			mlt_log_verbose( &m_consumer, "Failed to create video frame\n" );
			stop();
			return;
		}
		
		// Make the first line black for field order correction.
		uint8_t *buffer = 0;
		if ( S_OK == m_videoFrame->GetBytes( (void**) &buffer ) && buffer )
		{
			for ( int i = 0; i < m_width; i++ )
			{
				*buffer++ = 128;
				*buffer++ = 16;
			}
		}
		mlt_log_debug( &m_consumer, "created video frame\n" );
		mlt_deque_push_back( m_videoFrameQ, m_videoFrame );
	}
static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
	int error = 0;
	mlt_profile profile = (mlt_profile) mlt_frame_pop_get_image( frame );
	mlt_properties properties = MLT_FRAME_PROPERTIES(frame);
	mlt_image_format format_from = *format;
	mlt_image_format format_to = mlt_image_rgb24;
	
	error = mlt_frame_get_image( frame, image, format, width, height, writable );
	
	int frame_colorspace = mlt_properties_get_int( properties, "colorspace" );
	
	if ( !error && *format == mlt_image_yuv422 && profile->colorspace > 0 &&
	     frame_colorspace > 0 && frame_colorspace != profile->colorspace )
	{
		mlt_log_debug( NULL, "[filter avcolor_space] colorspace %d -> %d\n",
			frame_colorspace, profile->colorspace );
		
		// Convert to RGB using frame's colorspace
		error = convert_image( frame, image, &format_from, format_to );

		// Convert to YUV using profile's colorspace
		if ( !error )
		{
			*image = mlt_properties_get_data( properties, "image", NULL );
			format_from = mlt_image_rgb24;
			format_to = *format;
			mlt_properties_set_int( properties, "colorspace", profile->colorspace );
			error = convert_image( frame, image, &format_from, format_to );
			*image = mlt_properties_get_data( properties, "image", NULL );
		}
	}
	
	return error;
}
Exemple #4
0
GlslManager::~GlslManager()
{
	mlt_log_debug(get_service(), "%s\n", __FUNCTION__);
	cleanupContext();
	delete initEvent;
	delete closeEvent;
}
Exemple #5
0
Fichier : vdpau.c Projet : aib/mlt
static void vdpau_fini( producer_avformat self )
{
	if ( !self->vdpau )
		return;
	mlt_log_debug( NULL, "vdpau_fini (%x)\n", self->vdpau->device );
	if ( self->vdpau->decoder != VDP_INVALID_HANDLE )
		vdp_decoder_destroy( self->vdpau->decoder );
	if ( self->vdpau->device != VDP_INVALID_HANDLE )
		vdp_device_destroy( self->vdpau->device );
	free( self->vdpau );
	self->vdpau = NULL;
}
Exemple #6
0
void GlslManager::onInit( mlt_properties owner, GlslManager* filter )
{
	mlt_log_debug( filter->get_service(), "%s\n", __FUNCTION__ );
#ifdef WIN32
	std::string path = std::string(mlt_environment("MLT_APPDIR")).append("\\share\\movit");
#elif defined(__DARWIN__) && defined(RELOCATABLE)
	std::string path = std::string(mlt_environment("MLT_APPDIR")).append("/share/movit");
#else
	std::string path = std::string(getenv("MLT_MOVIT_PATH") ? getenv("MLT_MOVIT_PATH") : SHADERDIR);
#endif
	::init_movit( path, mlt_log_get_level() == MLT_LOG_DEBUG? MOVIT_DEBUG_ON : MOVIT_DEBUG_OFF );
	filter->set( "glsl_supported", movit_initialized );
}
static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
{
	/* Obtain properties of frame */
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );

	/* Obtain the producer for this frame */
	producer_ktitle this = mlt_properties_get_data( properties, "producer_kdenlivetitle", NULL );
	
	/* Obtain properties of producer */
	mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( &this->parent );
	
	*width = mlt_properties_get_int( properties, "rescale_width" );
	*height = mlt_properties_get_int( properties, "rescale_height" );
	
	/* Allocate the image */
	int size = *width * ( *height ) * 4;

	/* Allocate the image */
	*format = mlt_image_rgb24a;
	mlt_position time = mlt_producer_position( &this->parent ) + mlt_producer_get_in( &this->parent );
	if ( mlt_properties_get_int( producer_props, "force_reload" ) ) {
		if (mlt_properties_get_int( producer_props, "force_reload" ) > 1) read_xml(producer_props);
		mlt_properties_set_int( producer_props, "force_reload", 0 );
		drawKdenliveTitle( this, frame, *width, *height, time, 1);
	}
	else drawKdenliveTitle( this, frame, *width, *height, time, 0);

	// Get width and height (may have changed during the refresh)
	*width = mlt_properties_get_int( properties, "width" );
	*height = mlt_properties_get_int( properties, "height" );
		
	if ( this->current_image )
	{
		// Clone the image and the alpha
		int image_size = this->current_width * ( this->current_height ) * 4;
		uint8_t *image_copy = mlt_pool_alloc( image_size );
		memcpy( image_copy, this->current_image, image_size );
		// Now update properties so we free the copy after
		mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL );
		// We're going to pass the copy on
		*buffer = image_copy;		
		
		/* Update the frame */
		mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL );

		mlt_log_debug( MLT_PRODUCER_SERVICE( &this->parent ), "width:%d height:%d %s\n", *width, *height, mlt_image_format_name( *format ) );
	}

	return 0;
}
Exemple #8
0
	virtual ~DeckLinkConsumer()
	{
		mlt_log_debug( getConsumer(), "%s: entering\n",  __FUNCTION__ );

		SAFE_RELEASE( m_displayMode );
		SAFE_RELEASE( m_deckLinkKeyer );
		SAFE_RELEASE( m_deckLinkOutput );
		SAFE_RELEASE( m_deckLink );

		mlt_deque_close( m_aqueue );
		mlt_deque_close( m_frames );

		op(OP_EXIT, 0);
		mlt_log_debug( getConsumer(), "%s: waiting for op thread\n", __FUNCTION__ );
		pthread_join(m_op_thread, NULL);
		mlt_log_debug( getConsumer(), "%s: finished op thread\n", __FUNCTION__ );

		pthread_mutex_destroy(&m_op_lock);
		pthread_mutex_destroy(&m_op_arg_mutex);
		pthread_cond_destroy(&m_op_arg_cond);

		mlt_log_debug( getConsumer(), "%s: exiting\n", __FUNCTION__ );
	}
Exemple #9
0
void mlt_slices_close( mlt_slices ctx )
{
	int j;

	pthread_mutex_lock( &g_lock );

	mlt_log_debug( NULL, "%s:%d: ctx=[%p][%s] closing\n", __FUNCTION__, __LINE__, ctx, ctx->name );

	/* check reference count */
	if ( ctx->ref )
	{
		ctx->ref--;
		mlt_log_debug( NULL, "%s:%d: ctx=[%p][%s] new ref=%d\n", __FUNCTION__, __LINE__, ctx, ctx->name, ctx->ref );
		pthread_mutex_unlock( &g_lock );
		return;
	}
	pthread_mutex_unlock( &g_lock );

	/* notify to exit */
	ctx->f_exit = 1;
	pthread_mutex_lock( &ctx->cond_mutex );
	pthread_cond_broadcast( &ctx->cond_var_job);
	pthread_cond_broadcast( &ctx->cond_var_ready);
	pthread_mutex_unlock( &ctx->cond_mutex );

	/* wait for threads exit */
	for ( j = 0; j < ctx->count; j++ )
		pthread_join ( ctx->threads[j], NULL );

	/* destroy vars */
	pthread_cond_destroy ( &ctx->cond_var_ready );
	pthread_cond_destroy ( &ctx->cond_var_job );
	pthread_mutex_destroy ( &ctx->cond_mutex );

	/* free context */
	free ( ctx );
}
Exemple #10
0
Fichier : vdpau.c Projet : aib/mlt
static void vdpau_release_buffer( AVCodecContext *codec_context, AVFrame *frame )
{
	producer_avformat self = codec_context->opaque;
	if ( self->vdpau )
	{
		struct vdpau_render_state *render = (struct vdpau_render_state*) frame->data[0];
		mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "vdpau_release_buffer (%x)\n", render->surface );
		int i;

		render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
		for ( i = 0; i < 4; i++ )
			frame->data[i] = NULL;
		mlt_deque_push_back( self->vdpau->deque, render );
	}
}
Exemple #11
0
Fichier : vdpau.c Projet : aib/mlt
static int vdpau_get_buffer( AVCodecContext *codec_context, AVFrame *frame )
{
	int error = 0;
	producer_avformat self = codec_context->opaque;
	mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "vdpau_get_buffer\n" );
	
	if ( self->vdpau && mlt_deque_count( self->vdpau->deque ) )
	{
		struct vdpau_render_state *render = mlt_deque_pop_front( self->vdpau->deque );
		
		if ( render )
		{
			frame->data[0] = (uint8_t*) render;
			frame->data[1] = (uint8_t*) render;
			frame->data[2] = (uint8_t*) render;
			frame->linesize[0] = 0;
			frame->linesize[1] = 0;
			frame->linesize[2] = 0;
			frame->type = FF_BUFFER_TYPE_USER;
			render->state = FF_VDPAU_STATE_USED_FOR_REFERENCE;
			frame->reordered_opaque = codec_context->reordered_opaque;
			if ( frame->reference )
			{
				self->vdpau->ip_age[0] = self->vdpau->ip_age[1] + 1;
				self->vdpau->ip_age[1] = 1;
				self->vdpau->b_age++;
			}
			else
			{
				self->vdpau->ip_age[0] ++;
				self->vdpau->ip_age[1] ++;
				self->vdpau->b_age = 1;
			}
		}
		else
		{
			mlt_log_warning( MLT_PRODUCER_SERVICE(self->parent), "VDPAU surface underrun\n" );
			error = -1;
		}
	}
	else
	{
		mlt_log_warning( MLT_PRODUCER_SERVICE(self->parent), "VDPAU surface underrun\n" );
		error = -1;
	}
	
	return error;
}
Exemple #12
0
void mlt_slices_run( mlt_slices ctx, int jobs, mlt_slices_proc proc, void* cookie )
{
	struct mlt_slices_runtime_s runtime, *r = &runtime;

	/* lock */
	pthread_mutex_lock( &ctx->cond_mutex);

	/* check jobs count */
	if ( jobs < 0 )
		jobs = (-jobs) * ctx->count;
	if ( !jobs )
		jobs = ctx->count;

	/* setup runtime args */
	r->jobs = jobs;
	r->done = 0;
	r->curr = 0;
	r->proc = proc;
	r->cookie = cookie;
	r->next = NULL;

	/* attach job */
	if ( ctx->tail )
	{
		ctx->tail->next = r;
		ctx->tail = r;
	}
	else
	{
		ctx->head = ctx->tail = r;
	}

	/* notify workers */
	pthread_cond_broadcast( &ctx->cond_var_job );

	/* wait for end of task */
	while( !ctx->f_exit && ( r->done < r->jobs ) )
	{
		pthread_cond_wait( &ctx->cond_var_ready, &ctx->cond_mutex );
		mlt_log_debug( NULL, "%s:%d: ctx=[%p][%s] signalled\n", __FUNCTION__, __LINE__ , ctx, ctx->name );
	}

	pthread_mutex_unlock( &ctx->cond_mutex);
}
Exemple #13
0
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{

	mlt_filter filter = mlt_frame_pop_service( frame );
	*format = mlt_image_rgb24a;
	mlt_log_debug( MLT_FILTER_SERVICE( filter ), "frei0r %dx%d\n", *width, *height );
	int error = mlt_frame_get_image( frame, image, format, width, height, 0 );

	if ( error == 0 && *image )
	{
		double position = mlt_filter_get_position( filter, frame );
		mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
		double time = position / mlt_profile_fps( profile );
		int length = mlt_filter_get_length2( filter, frame );
		process_frei0r_item( MLT_FILTER_SERVICE(filter), position, time, length, frame, image, width, height );
	}

	return error;
}
Exemple #14
0
Fichier : vdpau.c Projet : aib/mlt
static void vdpau_producer_close( producer_avformat self )
{
	if ( self->vdpau )
	{
		mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "vdpau_producer_close\n" );
		int i;
		for ( i = 0; i < MAX_VDPAU_SURFACES; i++ )
		{
			if ( self->vdpau->render_states[i].surface != VDP_INVALID_HANDLE )
				vdp_surface_destroy( self->vdpau->render_states[i].surface );
			self->vdpau->render_states[i].surface = VDP_INVALID_HANDLE;
		}

		mlt_deque_close( self->vdpau->deque );
		if ( self->vdpau->buffer )
			mlt_pool_release( self->vdpau->buffer );
		self->vdpau->buffer = NULL;

		vdpau_fini( self );
	}
}
Exemple #15
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;
}
static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, mlt_image_format output_format )
{
	// Nothing to do!
	if ( *format == output_format )
		return 0;

	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );

	mlt_log_debug( NULL, "filter_movit_convert: %s -> %s\n",
		mlt_image_format_name( *format ), mlt_image_format_name( output_format ) );

	// Use CPU if glsl not initialized or not supported.
	GlslManager* glsl = GlslManager::get_instance();
	if ( !glsl || !glsl->get_int("glsl_supported" ) )
		return convert_on_cpu( frame, image, format, output_format );

	// Do non-GL image conversions on a CPU-based image converter.
	if ( *format != mlt_image_glsl && output_format != mlt_image_glsl && output_format != mlt_image_glsl_texture )
		return convert_on_cpu( frame, image, format, output_format );

	int error = 0;
	int width = mlt_properties_get_int( properties, "width" );
	int height = mlt_properties_get_int( properties, "height" );
	int img_size = mlt_image_format_size( *format, width, height, NULL );
	mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
	mlt_service service = MLT_PRODUCER_SERVICE(producer);
	GlslManager::get_instance()->lock_service( frame );
	EffectChain* chain = GlslManager::get_chain( service );
	MltInput* input = GlslManager::get_input( service );

	if ( !chain || !input ) {
		GlslManager::get_instance()->unlock_service( frame );
		return 2;
	}

	if ( *format != mlt_image_glsl ) {
		bool finalize_chain = false;
		if ( output_format == mlt_image_glsl_texture ) {
			// We might already have a texture from a previous conversion from mlt_image_glsl.
			glsl_texture texture = (glsl_texture) mlt_properties_get_data( properties, "movit.convert.texture", NULL );
			// XXX: requires a special property set on the frame by the app for now
			// because we do not have reliable way to clear the texture property
			// when a downstream filter has changed image.
			if ( texture && mlt_properties_get_int( properties, "movit.convert.use_texture") ) {
				*image = (uint8_t*) &texture->texture;
				mlt_frame_set_image( frame, *image, 0, NULL );
				mlt_properties_set_int( properties, "format", output_format );
				*format = output_format;
				GlslManager::get_instance()->unlock_service( frame );
				return error;
			} else {
				// Use a separate chain to convert image in RAM to OpenGL texture.
				// Use cached chain if available and compatible.
				Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
				chain = (EffectChain*) producer.get_data( "movit.convert.chain" );
				input = (MltInput*) producer.get_data( "movit.convert.input" );
				int w = producer.get_int( "movit.convert.width" );
				int h = producer.get_int( "movit.convert.height" );
				mlt_image_format f = (mlt_image_format) producer.get_int( "movit.convert.format" );
				if ( !chain || width != w || height != h || output_format != f ) {
					chain = new EffectChain( width, height );
					input = new MltInput( width, height );
					chain->add_input( input );
					chain->add_effect( new Mlt::VerticalFlip() );
					finalize_chain = true;
					producer.set( "movit.convert.chain", chain, 0, (mlt_destructor) delete_chain );
					producer.set( "movit.convert.input", input, 0 );
					producer.set( "movit.convert.width", width );
					producer.set( "movit.convert.height", height );
					producer.set( "movit.convert.format", output_format );
				}
			}
		}
		if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) { 
			input->useFlatInput( chain, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, width, height );
			input->set_pixel_data( *image );
		}
		else if ( *format == mlt_image_rgb24 ) {
			input->useFlatInput( chain, FORMAT_RGB, width, height );
			input->set_pixel_data( *image );
		}
		else if ( *format == mlt_image_yuv420p ) {
			ImageFormat image_format;
			YCbCrFormat ycbcr_format;
			if ( 709 == mlt_properties_get_int( properties, "colorspace" ) ) {
				image_format.color_space = COLORSPACE_REC_709;
				image_format.gamma_curve = GAMMA_REC_709;
				ycbcr_format.luma_coefficients = YCBCR_REC_709;
			} else if ( 576 == mlt_properties_get_int( properties, "height" ) ) {
				image_format.color_space = COLORSPACE_REC_601_625;
				image_format.gamma_curve = GAMMA_REC_601;
				ycbcr_format.luma_coefficients = YCBCR_REC_601;
			} else {
				image_format.color_space = COLORSPACE_REC_601_525;
				image_format.gamma_curve = GAMMA_REC_601;
				ycbcr_format.luma_coefficients = YCBCR_REC_601;
			}
			ycbcr_format.full_range = mlt_properties_get_int( properties, "force_full_luma" );
			ycbcr_format.chroma_subsampling_x = ycbcr_format.chroma_subsampling_y = 2;
			// TODO: make new frame properties set by producers
			ycbcr_format.cb_x_position = ycbcr_format.cr_x_position = 0.0f;
			ycbcr_format.cb_y_position = ycbcr_format.cr_y_position = 0.5f;
			input->useYCbCrInput( chain, image_format, ycbcr_format, width, height );
			input->set_pixel_data( *image );
		}
		else if ( *format == mlt_image_yuv422 ) {
			ImageFormat image_format;
			YCbCrFormat ycbcr_format;
			if ( 709 == mlt_properties_get_int( properties, "colorspace" ) ) {
				image_format.color_space = COLORSPACE_REC_709;
				image_format.gamma_curve = GAMMA_REC_709;
				ycbcr_format.luma_coefficients = YCBCR_REC_709;
			} else if ( 576 == height ) {
				image_format.color_space = COLORSPACE_REC_601_625;
				image_format.gamma_curve = GAMMA_REC_601;
				ycbcr_format.luma_coefficients = YCBCR_REC_601;
			} else {
				image_format.color_space = COLORSPACE_REC_601_525;
				image_format.gamma_curve = GAMMA_REC_601;
				ycbcr_format.luma_coefficients = YCBCR_REC_601;
			}
			ycbcr_format.full_range = mlt_properties_get_int( properties, "force_full_luma" );
			ycbcr_format.chroma_subsampling_x = 2;
			ycbcr_format.chroma_subsampling_y = 1;
			// TODO: make new frame properties set by producers
			ycbcr_format.cb_x_position = ycbcr_format.cr_x_position = 0.0f;
			ycbcr_format.cb_y_position = ycbcr_format.cr_y_position = 0.5f;
			input->useYCbCrInput( chain, image_format, ycbcr_format, width, height );
			
			// convert chunky to planar
			uint8_t* planar = (uint8_t*) mlt_pool_alloc( img_size );
			yuv422_to_yuv422p( *image, planar, width, height );
			input->set_pixel_data( planar );
			mlt_frame_set_image( frame, planar, img_size, mlt_pool_release );
		}
		// Finalize the separate conversion chain if needed.
		if ( finalize_chain )
			chain->finalize();
	}

	if ( output_format != mlt_image_glsl ) {
		glsl_fbo fbo = glsl->get_fbo( width, height );

		if ( output_format == mlt_image_glsl_texture ) {
			glsl_texture texture = glsl->get_texture( width, height, GL_RGBA );

			glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
			check_error();
			glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
			check_error();
			glBindFramebuffer( GL_FRAMEBUFFER, 0 );
			check_error();

			GlslManager::render( service, chain, fbo->fbo, width, height );

			glFinish();
			check_error();
			glBindFramebuffer( GL_FRAMEBUFFER, 0 );
			check_error();

			*image = (uint8_t*) &texture->texture;
			mlt_frame_set_image( frame, *image, 0, NULL );
			mlt_properties_set_data( properties, "movit.convert.texture", texture, 0,
				(mlt_destructor) GlslManager::release_texture, NULL );
			mlt_properties_set_int( properties, "format", output_format );
			*format = output_format;
		}
		else {
			// Use a PBO to hold the data we read back with glReadPixels()
			// (Intel/DRI goes into a slow path if we don't read to PBO)
			GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )?
				GL_RGBA : GL_RGB;
			img_size = width * height * ( gl_format == GL_RGB? 3 : 4 );
			glsl_pbo pbo = glsl->get_pbo( img_size );
			glsl_texture texture = glsl->get_texture( width, height, gl_format );

			if ( fbo && pbo && texture ) {
				// Set the FBO
				glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
				check_error();
				glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
				check_error();
				glBindFramebuffer( GL_FRAMEBUFFER, 0 );
				check_error();

				GlslManager::render( service, chain, fbo->fbo, width, height );
	
				// Read FBO into PBO
				glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
				check_error();
				glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
				check_error();
				glReadPixels( 0, 0, width, height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
				check_error();
	
				// Copy from PBO
				uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
				check_error();
				*image = (uint8_t*) mlt_pool_alloc( img_size );
				mlt_frame_set_image( frame, *image, img_size, mlt_pool_release );
				memcpy( *image, buf, img_size );

				if ( output_format == mlt_image_yuv422 || output_format == mlt_image_yuv420p ) {
					*format = mlt_image_rgb24;
					error = convert_on_cpu( frame, image, format, output_format );
				}
	
				// Release PBO and FBO
				glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
				check_error();
				glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
				check_error();
				glBindFramebuffer( GL_FRAMEBUFFER, 0 );
				check_error();
				glBindTexture( GL_TEXTURE_2D, 0 );
				check_error();
				mlt_properties_set_data( properties, "movit.convert.texture", texture, 0,
					(mlt_destructor) GlslManager::release_texture, NULL);
	
				mlt_properties_set_int( properties, "format", output_format );
				*format = output_format;
			}
			else {
				error = 1;
			}
		}
		if ( fbo ) GlslManager::release_fbo( fbo );
	}
	else {
		mlt_properties_set_int( properties, "format", output_format );
		*format = output_format;
	}
	GlslManager::get_instance()->unlock_service( frame );

	return error;
}
Exemple #17
0
    virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(
        IDeckLinkVideoInputFrame* video,
        IDeckLinkAudioInputPacket* audio )
    {
        if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "preview" ) &&
                mlt_producer_get_speed( getProducer() ) == 0.0 && !mlt_deque_count( m_queue ))
        {
            pthread_cond_broadcast( &m_condition );
            return S_OK;
        }

        // Create mlt_frame
        mlt_frame frame = mlt_frame_init( MLT_PRODUCER_SERVICE( getProducer() ) );

        // Copy video
        if ( video )
        {
            if ( !( video->GetFlags() & bmdFrameHasNoInputSource ) )
            {
                int size = video->GetRowBytes() * ( video->GetHeight() + m_vancLines );
                void* image = mlt_pool_alloc( size );
                void* buffer = 0;
                unsigned char* p = (unsigned char*) image;
                int n = size / 2;
                \
                // Initialize VANC lines to nominal black
                while ( --n )
                {
                    *p ++ = 16;
                    *p ++ = 128;
                }

                // Capture VANC
                if ( m_vancLines > 0 )
                {
                    IDeckLinkVideoFrameAncillary* vanc = 0;
                    if ( video->GetAncillaryData( &vanc ) == S_OK && vanc )
                    {
                        for ( int i = 1; i < m_vancLines + 1; i++ )
                        {
                            if ( vanc->GetBufferForVerticalBlankingLine( i, &buffer ) == S_OK )
                                swab( (char*) buffer, (char*) image + ( i - 1 ) * video->GetRowBytes(), video->GetRowBytes() );
                            else
                                mlt_log_debug( getProducer(), "failed capture vanc line %d\n", i );
                        }
                        SAFE_RELEASE(vanc);
                    }
                }

                // Capture image
                video->GetBytes( &buffer );
                if ( image && buffer )
                {
                    size =  video->GetRowBytes() * video->GetHeight();
                    swab( (char*) buffer, (char*) image + m_vancLines * video->GetRowBytes(), size );
                    mlt_frame_set_image( frame, (uint8_t*) image, size, mlt_pool_release );
                }
                else if ( image )
                {
                    mlt_log_verbose( getProducer(), "no video\n" );
                    mlt_pool_release( image );
                }
            }
            else
            {
                mlt_log_verbose( getProducer(), "no signal\n" );
                mlt_frame_close( frame );
                frame = 0;
            }

            // Get timecode
            IDeckLinkTimecode* timecode = 0;
            if ( video->GetTimecode( bmdTimecodeVITC, &timecode ) == S_OK && timecode )
            {
                DLString timecodeString = 0;

                if ( timecode->GetString( &timecodeString ) == S_OK )
                {
                    char* s = getCString( timecodeString );
                    mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "meta.attr.vitc.markup", s );
                    mlt_log_debug( getProducer(), "timecode %s\n", s );
                    freeCString( s );
                }
                freeDLString( timecodeString );
                SAFE_RELEASE( timecode );
            }
        }
        else
        {
            mlt_log_verbose( getProducer(), "no video\n" );
            mlt_frame_close( frame );
            frame = 0;
        }

        // Copy audio
        if ( frame && audio )
        {
            int channels = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "channels" );
            int size = audio->GetSampleFrameCount() * channels * sizeof(int16_t);
            mlt_audio_format format = mlt_audio_s16;
            void* pcm = mlt_pool_alloc( size );
            void* buffer = 0;

            audio->GetBytes( &buffer );
            if ( buffer )
            {
                memcpy( pcm, buffer, size );
                mlt_frame_set_audio( frame, pcm, format, size, mlt_pool_release );
                mlt_properties_set_int( MLT_FRAME_PROPERTIES(frame), "audio_samples", audio->GetSampleFrameCount() );
            }
            else
            {
                mlt_log_verbose( getProducer(), "no audio\n" );
                mlt_pool_release( pcm );
            }
        }
        else
        {
            mlt_log_verbose( getProducer(), "no audio\n" );
        }

        // Put frame in queue
        if ( frame )
        {
            int queueMax = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "buffer" );
            pthread_mutex_lock( &m_mutex );
            if ( mlt_deque_count( m_queue ) < queueMax )
            {
                mlt_deque_push_back( m_queue, frame );
                pthread_cond_broadcast( &m_condition );
            }
            else
            {
                mlt_frame_close( frame );
                mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "dropped", ++m_dropped );
                mlt_log_warning( getProducer(), "frame dropped %d\n", m_dropped );
            }
            pthread_mutex_unlock( &m_mutex );
        }

        return S_OK;
    }
Exemple #18
0
static int jack_process (jack_nframes_t frames, void * data)
{
	mlt_filter filter = (mlt_filter) data;
 	mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
	int channels = mlt_properties_get_int( properties, "channels" );
	int frame_size = mlt_properties_get_int( properties, "_samples" ) * sizeof(float);
	int sync = mlt_properties_get_int( properties, "_sync" );
	int err = 0;
	int i;
	static int total_size = 0;
  
	jack_ringbuffer_t **output_buffers = mlt_properties_get_data( properties, "output_buffers", NULL );
	if ( output_buffers == NULL )
		return 0;
	jack_ringbuffer_t **input_buffers = mlt_properties_get_data( properties, "input_buffers", NULL );
	jack_port_t **jack_output_ports = mlt_properties_get_data( properties, "jack_output_ports", NULL );
	jack_port_t **jack_input_ports = mlt_properties_get_data( properties, "jack_input_ports", NULL );
	float **jack_output_buffers = mlt_properties_get_data( properties, "jack_output_buffers", NULL );
	float **jack_input_buffers = mlt_properties_get_data( properties, "jack_input_buffers", NULL );
	pthread_mutex_t *output_lock = mlt_properties_get_data( properties, "output_lock", NULL );
	pthread_cond_t *output_ready = mlt_properties_get_data( properties, "output_ready", NULL );
	
	for ( i = 0; i < channels; i++ )
	{
		size_t jack_size = ( frames * sizeof(float) );
		size_t ring_size;
		
		// Send audio through out port
		jack_output_buffers[i] = jack_port_get_buffer( jack_output_ports[i], frames );
		if ( ! jack_output_buffers[i] )
		{
			mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for output port %d\n", i );
			err = 1;
			break;
		}
		ring_size = jack_ringbuffer_read_space( output_buffers[i] );
		jack_ringbuffer_read( output_buffers[i], ( char * )jack_output_buffers[i], ring_size < jack_size ? ring_size : jack_size );
		if ( ring_size < jack_size )
			memset( &jack_output_buffers[i][ring_size], 0, jack_size - ring_size );
		
		// Return audio through in port
		jack_input_buffers[i] = jack_port_get_buffer( jack_input_ports[i], frames );
		if ( ! jack_input_buffers[i] )
		{
			mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for input port %d\n", i );
			err = 1;
			break;
		}
		
		// Do not start returning audio until we have sent first mlt frame
		if ( sync && i == 0 && frame_size > 0 )
			total_size += ring_size;
		mlt_log_debug( MLT_FILTER_SERVICE(filter), "sync %d frame_size %d ring_size %zu jack_size %zu\n", sync, frame_size, ring_size, jack_size );
		
		if ( ! sync || ( frame_size > 0  && total_size >= frame_size ) )
		{
			ring_size = jack_ringbuffer_write_space( input_buffers[i] );
			jack_ringbuffer_write( input_buffers[i], ( char * )jack_input_buffers[i], ring_size < jack_size ? ring_size : jack_size );
			
			if ( sync )
			{
				// Tell mlt that audio is available
				pthread_mutex_lock( output_lock);
				pthread_cond_signal( output_ready );
				pthread_mutex_unlock( output_lock);

				// Clear sync phase
				mlt_properties_set_int( properties, "_sync", 0 );
			}
		}
	}

	// Often jackd does not send the stopped event through the JackSyncCallback
	jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
	jack_position_t jack_pos;
	jack_transport_state_t state = jack_transport_query( jack_client, &jack_pos );
	int transport_state = mlt_properties_get_int( properties, "_transport_state" );
	if ( state != transport_state )
	{
		mlt_properties_set_int( properties, "_transport_state", state );
		if ( state == JackTransportStopped )
			jack_sync( state, &jack_pos, filter );
	}

	return err;
}
Exemple #19
0
static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *format, mlt_audio_format requested_format )
{
	int error = 1;
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
	int channels = mlt_properties_get_int( properties, "audio_channels" );
	int samples = mlt_properties_get_int( properties, "audio_samples" );
	int size = mlt_audio_format_size( requested_format, samples, channels );

	if ( *format != requested_format )
	{
		mlt_log_debug( NULL, "[filter audioconvert] %s -> %s %d channels %d samples\n",
			mlt_audio_format_name( *format ), mlt_audio_format_name( requested_format ),
			channels, samples );
		switch ( *format )
		{
		case mlt_audio_s16:
			switch ( requested_format )
			{
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					int16_t *q = (int16_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = (int32_t) *q << 16;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					int16_t *q = (int16_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = (float)( *q ) / 32768.0;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int16_t *q = (int16_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = (int32_t) *q++ << 16;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int16_t *q = (int16_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = (float)( *q++ ) / 32768.0;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_t *p = buffer;
				int16_t *q = (int16_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( *q++ >> 8 ) + 128;
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_s32:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_t *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
						*p++ = *( q + c * samples + s ) >> 16;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = (float)( *q++ ) / 2147483648.0;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
						*p++ = *( q + c * samples + s );
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
					{
						float f = (float)( *( q + c * samples + s ) ) / 2147483648.0;
						f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
						*p++ = f;
					}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_t *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
						*p++ = ( q[c * samples + s] >> 24 ) + 128;
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_float:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_t *p = buffer;
				float *q = (float*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
					{
						float f = *( q + c * samples + s );
						f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
						*p++ = 32767 * f;
					}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				float *q = (float*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = *q++;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				float *q = (float*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
					{
						float f = *( q + c * samples + s );
						f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
						*p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
					}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				float *q = (float*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
						*p++ = *( q + c * samples + s );
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_t *p = buffer;
				float *q = (float*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
					{
						float f = *( q + c * samples + s );
						f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
						*p++ = ( 127 * f ) + 128;
					}
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_s32le:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_t *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = *q++ >> 16;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					int32_t *q = (int32_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = *q;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					int32_t *q = (int32_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = (float)( *q ) / 2147483648.0;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = (float)( *q++ ) / 2147483648.0;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_t *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( *q++ >> 24 ) + 128;
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_f32le:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_t *p = buffer;
				float *q = (float*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = *q++;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = 32767 * f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					float *q = (float*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = *q;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					float *q = (float*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						float f = *q;
						f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
						*p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				float *q = (float*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = *q++;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_t *p = buffer;
				float *q = (float*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = *q++;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = ( 127 * f ) + 128;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_u8:
			switch ( requested_format )
			{
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					uint8_t *q = (uint8_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = ( (int32_t) *q - 128 ) << 24;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					uint8_t *q = (uint8_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = ( (float) *q - 128 ) / 256.0f;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_t *p = buffer;
				uint8_t *q = (uint8_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( (int16_t) *q++ - 128 ) << 8;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				uint8_t *q = (uint8_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( (int32_t) *q++ - 128 ) << 24;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				uint8_t *q = (uint8_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = ( (float) *q++ - 128 ) / 256.0f;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		default:
			break;
		}
	}
Exemple #20
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;
}
Exemple #21
0
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
{
	int error = 0;
	mlt_profile profile = mlt_frame_pop_service( frame );

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

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

	int left    = mlt_properties_get_int( properties, "crop.left" );
	int right   = mlt_properties_get_int( properties, "crop.right" );
	int top     = mlt_properties_get_int( properties, "crop.top" );
	int bottom  = mlt_properties_get_int( properties, "crop.bottom" );

	// Request the image at its original resolution
	if ( left || right || top || bottom )
	{
		mlt_properties_set_int( properties, "rescale_width", mlt_properties_get_int( properties, "crop.original_width" ) );
		mlt_properties_set_int( properties, "rescale_height", mlt_properties_get_int( properties, "crop.original_height" ) );
	}

	// Now get the image
	error = mlt_frame_get_image( frame, image, format, width, height, writable );

	int owidth  = *width - left - right;
	int oheight = *height - top - bottom;
	owidth = owidth < 0 ? 0 : owidth;
	oheight = oheight < 0 ? 0 : oheight;

	if ( ( owidth != *width || oheight != *height ) &&
		error == 0 && *image != NULL && owidth > 0 && oheight > 0 )
	{
		int bpp;

		// Subsampled YUV is messy and less precise.
		if ( *format == mlt_image_yuv422 && frame->convert_image )
		{
			mlt_image_format requested_format = mlt_image_rgb24;
			frame->convert_image( frame, image, format, requested_format );
		}
	
		mlt_log_debug( NULL, "[filter crop] %s %dx%d -> %dx%d\n", mlt_image_format_name(*format),
				 *width, *height, owidth, oheight);

		// Provides a manual override for misreported field order
		if ( mlt_properties_get( properties, "meta.top_field_first" ) )
		{
			mlt_properties_set_int( properties, "top_field_first", mlt_properties_get_int( properties, "meta.top_field_first" ) );
			mlt_properties_set_int( properties, "meta.top_field_first", 0 );
		}

		if ( top % 2 )
			mlt_properties_set_int( properties, "top_field_first", !mlt_properties_get_int( properties, "top_field_first" ) );
		
		// Create the output image
		int size = mlt_image_format_size( *format, owidth, oheight, &bpp );
		uint8_t *output = mlt_pool_alloc( size );
		if ( output )
		{
			// Call the generic resize
			crop( *image, output, bpp, *width, *height, left, right, top, bottom );

			// Now update the frame
			mlt_frame_set_image( frame, output, size, mlt_pool_release );
			*image = output;
		}

		// We should resize the alpha too
		uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
		int alpha_size = 0;
		mlt_properties_get_data( properties, "alpha", &alpha_size );
		if ( alpha && alpha_size >= ( *width * *height ) )
		{
			uint8_t *newalpha = mlt_pool_alloc( owidth * oheight );
			if ( newalpha )
			{
				crop( alpha, newalpha, 1, *width, *height, left, right, top, bottom );
				mlt_frame_set_alpha( frame, newalpha, owidth * oheight, mlt_pool_release );
			}
		}
		*width = owidth;
		*height = oheight;
	}

	return error;
}
Exemple #22
0
static jack_rack_t* initialise_jack_rack( mlt_properties properties, int channels )
{
	jack_rack_t *jackrack = NULL;
	char *resource = mlt_properties_get( properties, "resource" );
	if ( !resource && mlt_properties_get( properties, "src" ) )
		resource = mlt_properties_get( properties, "src" );

	// Start JackRack
	if ( resource || mlt_properties_get_int64( properties, "_pluginid" ) )
	{
		// Create JackRack without Jack client name so that it only uses LADSPA
		jackrack = jack_rack_new( NULL, channels );
		mlt_properties_set_data( properties, "jackrack", jackrack, 0,
			(mlt_destructor) jack_rack_destroy, NULL );

		if ( resource )
			// Load JACK Rack XML file
			jack_rack_open_file( jackrack, resource );
		else if ( mlt_properties_get_int64( properties, "_pluginid" ) )
		{
			// Load one LADSPA plugin by its UniqueID
			unsigned long id = mlt_properties_get_int64( properties, "_pluginid" );
			plugin_desc_t *desc = plugin_mgr_get_any_desc( jackrack->plugin_mgr, id );
			plugin_t *plugin;
			if ( desc && ( plugin = jack_rack_instantiate_plugin( jackrack, desc ) ) )
			{
				plugin->enabled = TRUE;
				process_add_plugin( jackrack->procinfo, plugin );
				mlt_properties_set_int( properties, "instances", plugin->copies );
			}
			else
			{
				mlt_log_error( properties, "failed to load plugin %lu\n", id );
				return jackrack;
			}

			if ( plugin && plugin->desc && plugin->copies == 0 )
			{
				// Calculate the number of channels that will work with this plugin
				int request_channels = plugin->desc->channels;
				while ( request_channels < channels )
					request_channels += plugin->desc->channels;

				if ( request_channels != channels )
				{
					// Try to load again with a compatible number of channels.
					mlt_log_warning( properties, "Not compatible with %d channels. Requesting %d channels instead.\n",
						channels, request_channels );
					jack_rack_destroy( jackrack );
					jackrack = initialise_jack_rack( properties, request_channels );
				}
				else
				{
					mlt_log_error( properties, "Invalid plugin configuration: %lu\n", id );
					return jackrack;
				}
			}

			if ( plugin && plugin->desc && plugin->copies )
				mlt_log_debug( properties, "Plugin Initialized. Channels: %lu\tCopies: %d\tTotal: %lu\n", plugin->desc->channels, plugin->copies, jackrack->channels );
		}
	}
	return jackrack;
}
Exemple #23
0
Fichier : vdpau.c Projet : aib/mlt
static int vdpau_decoder_init( producer_avformat self )
{
	mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "vdpau_decoder_init\n" );
	int success = 1;
	
	self->video_codec->opaque = self;
	self->video_codec->get_format = vdpau_get_format;
	self->video_codec->get_buffer = vdpau_get_buffer;
	self->video_codec->release_buffer = vdpau_release_buffer;
	self->video_codec->draw_horiz_band = vdpau_draw_horiz;
	self->video_codec->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
	self->video_codec->pix_fmt = PIX_FMT_VDPAU_H264;
	
	VdpDecoderProfile profile = VDP_DECODER_PROFILE_H264_HIGH;
	uint32_t max_references = self->video_codec->refs;
	pthread_mutex_lock( &mlt_sdl_mutex );
	VdpStatus status = vdp_decoder_create( self->vdpau->device,
		profile, self->video_codec->width, self->video_codec->height, max_references, &self->vdpau->decoder );
	pthread_mutex_unlock( &mlt_sdl_mutex );
	
	if ( status == VDP_STATUS_OK )
	{
			int i, n = FFMIN( self->video_codec->refs + 2, MAX_VDPAU_SURFACES );

			self->vdpau->deque = mlt_deque_init();
			for ( i = 0; i < n; i++ )
			{
				if ( VDP_STATUS_OK == vdp_surface_create( self->vdpau->device, VDP_CHROMA_TYPE_420,
					self->video_codec->width, self->video_codec->height, &self->vdpau->render_states[i].surface ) )
				{
					mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "successfully created VDPAU surface %x\n",
						self->vdpau->render_states[i].surface );
					mlt_deque_push_back( self->vdpau->deque, &self->vdpau->render_states[i] );
				}
				else
				{
					mlt_log_info( MLT_PRODUCER_SERVICE(self->parent), "failed to create VDPAU surface %dx%d\n",
						self->video_codec->width, self->video_codec->height );
					while ( mlt_deque_count( self->vdpau->deque ) )
					{
						struct vdpau_render_state *render = mlt_deque_pop_front( self->vdpau->deque );
						vdp_surface_destroy( render->surface );
					}
					mlt_deque_close( self->vdpau->deque );
					success = 0;
					break;
				}
			}
			if ( self->vdpau )
				self->vdpau->b_age = self->vdpau->ip_age[0] = self->vdpau->ip_age[1] = 256*256*256*64; // magic from Avidemux
	}
	else
	{
		success = 0;
		self->vdpau->decoder = VDP_INVALID_HANDLE;
		mlt_log_error( MLT_PRODUCER_SERVICE(self->parent), "VDPAU failed to initialize decoder (%s)\n",
			vdp_get_error_string( status ) );
	}
	
	return success;
}
Exemple #24
0
static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
	// Get the filter service
	mlt_filter filter = mlt_frame_pop_audio( frame );

	// Get the filter properties
	mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );

	// Get the resample information
	int output_rate = mlt_properties_get_int( filter_properties, "frequency" );

	// If no resample frequency is specified, default to requested value
	if ( output_rate == 0 )
		output_rate = *frequency;

	// Get the producer's audio
	int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
	if ( error ) return error;

	// Return now if no work to do
	if ( output_rate != *frequency && *frequency > 0 && *channels > 0 )
	{
		mlt_log_debug( MLT_FILTER_SERVICE(filter), "channels %d samples %d frequency %d -> %d\n",
			*channels, *samples, *frequency, output_rate );

		// Do not convert to float unless we need to change the rate
		if ( *format != mlt_audio_f32le )
			frame->convert_audio( frame, buffer, format, mlt_audio_f32le );

		mlt_service_lock( MLT_FILTER_SERVICE(filter) );

		SRC_DATA data;
		data.data_in = *buffer;
		data.data_out = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
		data.src_ratio = ( float ) output_rate / ( float ) *frequency;
		data.input_frames = *samples;
		data.output_frames = BUFFER_LEN / *channels;
		data.end_of_input = 0;

		SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL );
		if ( !state || mlt_properties_get_int( filter_properties, "channels" ) != *channels )
		{
			// Recreate the resampler if the number of channels changed
			state = src_new( RESAMPLE_TYPE, *channels, &error );
			mlt_properties_set_data( filter_properties, "state", state, 0, (mlt_destructor) src_delete, NULL );
			mlt_properties_set_int( filter_properties, "channels", *channels );
		}

		// Resample the audio
		error = src_process( state, &data );
		if ( !error )
		{
			// Update output variables
			*samples = data.output_frames_gen;
			*frequency = output_rate;
			*buffer = data.data_out;
		}
		else
		{
			mlt_log_error( MLT_FILTER_SERVICE( filter ), "%s %d,%d,%d\n", src_strerror( error ), *frequency, *samples, output_rate );
		}
		mlt_service_unlock( MLT_FILTER_SERVICE(filter) );
	}

	return error;
}
Exemple #25
0
static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
{
	int error = 0;
	
	// Obtain properties of frame and producer
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
	producer_qimage self = mlt_properties_get_data( properties, "producer_qimage", NULL );
	mlt_producer producer = &self->parent;

	*width = mlt_properties_get_int( properties, "rescale_width" );
	*height = mlt_properties_get_int( properties, "rescale_height" );

	mlt_service_lock( MLT_PRODUCER_SERVICE( &self->parent ) );

	// Refresh the image
	self->qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
	self->qimage = mlt_cache_item_data( self->qimage_cache, NULL );
	self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" );
	self->current_image = mlt_cache_item_data( self->image_cache, NULL );
	self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" );
	self->current_alpha = mlt_cache_item_data( self->alpha_cache, NULL );
	refresh_image( self, frame, *format, *width, *height );

	// Get width and height (may have changed during the refresh)
	*width = mlt_properties_get_int( properties, "width" );
	*height = mlt_properties_get_int( properties, "height" );
	*format = self->format;

	// NB: Cloning is necessary with this producer (due to processing of images ahead of use)
	// The fault is not in the design of mlt, but in the implementation of the qimage producer...
	if ( self->current_image )
	{
		// Clone the image and the alpha
		int image_size = mlt_image_format_size( self->format, self->current_width, self->current_height, NULL );
		uint8_t *image_copy = mlt_pool_alloc( image_size );
		memcpy( image_copy, self->current_image, image_size );
		// Now update properties so we free the copy after
		mlt_frame_set_image( frame, image_copy, image_size, mlt_pool_release );
		// We're going to pass the copy on
		*buffer = image_copy;
		mlt_log_debug( MLT_PRODUCER_SERVICE( &self->parent ), "%dx%d (%s)\n",
			self->current_width, self->current_height, mlt_image_format_name( *format ) );
		// Clone the alpha channel
		if ( self->current_alpha )
		{
			image_copy = mlt_pool_alloc( self->current_width * self->current_height );
			memcpy( image_copy, self->current_alpha, self->current_width * self->current_height );
			mlt_frame_set_alpha( frame, image_copy, self->current_width * self->current_height, mlt_pool_release );
		}
	}
	else
	{
		error = 1;
	}

	// Release references and locks
	mlt_cache_item_close( self->qimage_cache );
	mlt_cache_item_close( self->image_cache );
	mlt_cache_item_close( self->alpha_cache );
	mlt_service_unlock( MLT_PRODUCER_SERVICE( &self->parent ) );

	return error;
}
Exemple #26
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;
}
Exemple #27
0
static void* mlt_slices_worker( void* p )
{
	int id, idx;
	struct mlt_slices_runtime_s* r;
	mlt_slices ctx = (mlt_slices)p;

	mlt_log_debug( NULL, "%s:%d: ctx=[%p][%s] entering\n", __FUNCTION__, __LINE__ , ctx, ctx->name );

	pthread_mutex_lock( &ctx->cond_mutex );

	id = ctx->readys;
	ctx->readys++;

	while ( 1 )
	{
		mlt_log_debug( NULL, "%s:%d: ctx=[%p][%s] waiting\n", __FUNCTION__, __LINE__ , ctx, ctx->name );

		/* wait for new jobs */
		while( !ctx->f_exit && !( r = ctx->head ) )
			pthread_cond_wait( &ctx->cond_var_job, &ctx->cond_mutex );

		if ( ctx->f_exit )
			break;

		if ( !r )
			continue;

		/* check if no new job */
		if ( r->curr == r->jobs )
		{
			ctx->head = ctx->head->next;
			if ( !ctx->head )
				ctx->tail = NULL;
			mlt_log_debug( NULL, "%s:%d: new ctx->head=%p\n", __FUNCTION__, __LINE__, ctx->head );
			continue;
		};

		/* new job id */
		idx = r->curr;
		r->curr++;

		/* run job */
		pthread_mutex_unlock( &ctx->cond_mutex );
		mlt_log_debug( NULL, "%s:%d: running job: id=%d, idx=%d/%d, pool=[%s]\n", __FUNCTION__, __LINE__,
			id, idx, r->jobs, ctx->name );
		r->proc( id, idx, r->jobs, r->cookie );
		pthread_mutex_lock( &ctx->cond_mutex );

		/* increase done jobs counter */
		r->done++;

		/* notify we fininished last job */
		if ( r->done == r->jobs )
		{
			mlt_log_debug( NULL, "%s:%d: pthread_cond_signal( &ctx->cond_var_ready )\n", __FUNCTION__, __LINE__ );
			pthread_cond_broadcast( &ctx->cond_var_ready );
		}
	}

	pthread_mutex_unlock( &ctx->cond_mutex );

	return NULL;
}
Exemple #28
0
static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
	// Get the filter service
	mlt_filter filter = mlt_frame_pop_audio( frame );

	// Get the filter properties
	mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );

	mlt_service_lock( MLT_FILTER_SERVICE( filter ) );

	// Get the resample information
	int output_rate = mlt_properties_get_int( filter_properties, "frequency" );
	int16_t *sample_buffer = mlt_properties_get_data( filter_properties, "buffer", NULL );

	// Obtain the resample context if it exists
	ReSampleContext *resample = mlt_properties_get_data( filter_properties, "audio_resample", NULL );

	// If no resample frequency is specified, default to requested value
	if ( output_rate == 0 )
		output_rate = *frequency;

	// Get the producer's audio
	int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
	if ( error ) return error;

	// Return now if no work to do
	if ( output_rate != *frequency )
	{
		// Will store number of samples created
		int used = 0;

		mlt_log_debug( MLT_FILTER_SERVICE(filter), "channels %d samples %d frequency %d -> %d\n",
			*channels, *samples, *frequency, output_rate );

		// Do not convert to s16 unless we need to change the rate
		if ( *format != mlt_audio_s16 )
		{
			*format = mlt_audio_s16;
			mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
		}

		// Create a resampler if nececessary
		if ( resample == NULL || *frequency != mlt_properties_get_int( filter_properties, "last_frequency" ) )
		{
			// Create the resampler
			resample = av_audio_resample_init( *channels, *channels, output_rate, *frequency,
				AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16, 16, 10, 0, 0.8 );

			// And store it on properties
			mlt_properties_set_data( filter_properties, "audio_resample", resample, 0, ( mlt_destructor )audio_resample_close, NULL );

			// And remember what it was created for
			mlt_properties_set_int( filter_properties, "last_frequency", *frequency );
		}

		mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );

		// Resample the audio
		used = audio_resample( resample, sample_buffer, *buffer, *samples );
		int size = used * *channels * sizeof( int16_t );

		// Resize if necessary
		if ( used > *samples )
		{
			*buffer = mlt_pool_realloc( *buffer, size );
			mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
		}

		// Copy samples
		memcpy( *buffer, sample_buffer, size );

		// Update output variables
		*samples = used;
		*frequency = output_rate;
	}
	else
	{
		mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
	}

	return error;
}
Exemple #29
0
Fichier : vdpau.c Projet : aib/mlt
static int vdpau_init( producer_avformat self )
{
	if ( !vdpau_supported )
		return 0;
	mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "vdpau_init\n" );
	int success = 0;
	mlt_properties properties = MLT_PRODUCER_PROPERTIES( self->parent );
	Display *display = XOpenDisplay( NULL );
	
	if ( !display || mlt_properties_get_int( properties, "novdpau" )
	     || ( getenv( "MLT_NO_VDPAU" ) && strcmp( getenv( "MLT_NO_VDPAU" ), "1" ) == 0 ) )
		return success;

	void *object = NULL;
	if ( !vdpau_init_done )
	{
		int flags = RTLD_NOW;
		object = dlopen( "/usr/lib/libvdpau.so", flags );
#ifdef ARCH_X86_64
		if ( !object )
			object = dlopen( "/usr/lib64/libvdpau.so", flags );
		if ( !object )
			object = dlopen( "/usr/lib/x86_64-linux-gnu/libvdpau.so.1", flags );
#elif ARCH_X86
		if ( !object )
			object = dlopen( "/usr/lib/i386-linux-gnu/libvdpau.so.1", flags );
#endif
		if ( !object )
			object = dlopen( "/usr/local/lib/libvdpau.so", flags );
		if ( object )
			vdpau_device_create_x11 = dlsym( object, "vdp_device_create_x11" );
		else
		{
			mlt_log( MLT_PRODUCER_SERVICE(self->parent), MLT_LOG_WARNING, "%s: failed to dlopen libvdpau.so\n  (%s)\n", __FUNCTION__, dlerror() );
			// Don't try again.
			vdpau_supported = 0;
			return success;
		}
	}
			
	if ( vdpau_device_create_x11 )
	{
		int screen = mlt_properties_get_int( properties, "x11_screen" );

		self->vdpau = calloc( 1, sizeof( *self->vdpau ) );
		self->vdpau->device = VDP_INVALID_HANDLE;
		self->vdpau->decoder = VDP_INVALID_HANDLE;
				
		mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "X11 Display = %p\n", display );
		if ( VDP_STATUS_OK == vdpau_device_create_x11( display, screen, &self->vdpau->device, &vdp_get_proc_address ) )
		{
			if ( !vdpau_init_done ) {
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_GET_ERROR_STRING, (void**) &vdp_get_error_string );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_GET_API_VERSION, (void**) &vdp_get_api_version );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_GET_INFORMATION_STRING, (void**) &vdp_get_information_string );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE, (void**) &vdp_surface_create );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, (void**) &vdp_surface_destroy );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, (void**) &vdp_surface_get_bits );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_DECODER_CREATE, (void**) &vdp_decoder_create );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_DECODER_DESTROY, (void**) &vdp_decoder_destroy );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_DECODER_RENDER, (void**) &vdp_decoder_render );
				vdp_get_proc_address( self->vdpau->device, VDP_FUNC_ID_DEVICE_DESTROY, (void**) &vdp_device_destroy );
				vdpau_init_done = 1;
			}
			success = 1;
		}
	}
	
	if ( !success )
	{
		mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "VDPAU failed to initialize device\n" );
		if ( object )
			dlclose( object );
		free( self->vdpau );
		self->vdpau = NULL;
	}

	return success;
}
Exemple #30
0
static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, mlt_image_format output_format )
{
	mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
	int width = mlt_properties_get_int( properties, "width" );
	int height = mlt_properties_get_int( properties, "height" );
	int error = 0;

	if ( *format != output_format )
	{
		mlt_profile profile = mlt_service_profile(
			MLT_PRODUCER_SERVICE( mlt_frame_get_original_producer( frame ) ) );
		int profile_colorspace = profile ? profile->colorspace : 601;
		int colorspace = mlt_properties_get_int( properties, "colorspace" );
		int force_full_luma = 0;
		
		mlt_log_debug( NULL, "[filter avcolor_space] %s -> %s @ %dx%d space %d->%d\n",
			mlt_image_format_name( *format ), mlt_image_format_name( output_format ),
			width, height, colorspace, profile_colorspace );

		int in_fmt = convert_mlt_to_av_cs( *format );
		int out_fmt = convert_mlt_to_av_cs( output_format );
		int size = FFMAX( avpicture_get_size( out_fmt, width, height ),
			mlt_image_format_size( output_format, width, height, NULL ) );
		uint8_t *output = mlt_pool_alloc( size );

		if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl )
		{
			register int len = width * height;
			uint8_t *alpha = mlt_pool_alloc( len );

			if ( alpha )
			{
				// Extract the alpha mask from the RGBA image using Duff's Device
				register uint8_t *s = *image + 3; // start on the alpha component
				register uint8_t *d = alpha;
				register int n = ( len + 7 ) / 8;

				switch ( len % 8 )
				{
					case 0:	do { *d++ = *s; s += 4;
					case 7:		 *d++ = *s; s += 4;
					case 6:		 *d++ = *s; s += 4;
					case 5:		 *d++ = *s; s += 4;
					case 4:		 *d++ = *s; s += 4;
					case 3:		 *d++ = *s; s += 4;
					case 2:		 *d++ = *s; s += 4;
					case 1:		 *d++ = *s; s += 4;
							}
							while ( --n > 0 );
				}
				mlt_frame_set_alpha( frame, alpha, len, mlt_pool_release );
			}
		}

		// Update the output
		if ( !av_convert_image( output, *image, out_fmt, in_fmt, width, height,
								colorspace, profile_colorspace, force_full_luma ) )
		{
			// The new colorspace is only valid if destination is YUV.
			if ( output_format == mlt_image_yuv422 || output_format == mlt_image_yuv420p )
				mlt_properties_set_int( properties, "colorspace", profile_colorspace );
		}
		*image = output;
		*format = output_format;
		mlt_frame_set_image( frame, output, size, mlt_pool_release );
		mlt_properties_set_int( properties, "format", output_format );

		if ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )
		{
			register int len = width * height;
			int alpha_size = 0;
			uint8_t *alpha = mlt_frame_get_alpha( frame );
			mlt_properties_get_data( properties, "alpha", &alpha_size );

			if ( alpha && alpha_size >= len )
			{
				// Merge the alpha mask from into the RGBA image using Duff's Device
				register uint8_t *s = alpha;
				register uint8_t *d = *image + 3; // start on the alpha component
				register int n = ( len + 7 ) / 8;

				switch ( len % 8 )
				{
					case 0:	do { *d = *s++; d += 4;
					case 7:		 *d = *s++; d += 4;
					case 6:		 *d = *s++; d += 4;
					case 5:		 *d = *s++; d += 4;
					case 4:		 *d = *s++; d += 4;
					case 3:		 *d = *s++; d += 4;
					case 2:		 *d = *s++; d += 4;
					case 1:		 *d = *s++; d += 4;
							}
							while ( --n > 0 );
				}
			}
		}
	}
	return error;
}