From f9c7e4e64fe57451a17ef25a727c8d3387ee1737 Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Wed, 24 Mar 2004 11:49:37 +0000 Subject: [PATCH] Tractor frame handling reworked; fix to composite for key diffs of 1; added mlt_consumer_new for consistency git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@236 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/framework/mlt_consumer.c | 16 +++++ src/framework/mlt_consumer.h | 1 + src/framework/mlt_tractor.c | 95 +++++++++++++++++++++--------- src/modules/core/transition_composite.c | 34 ++++++++--- src/modules/resample/filter_resample.c | 35 ++++++----- 5 files changed, 127 insertions(+), 54 deletions(-) diff --git a/src/framework/mlt_consumer.c b/src/framework/mlt_consumer.c index 5249d9f..2a05df1 100644 --- a/src/framework/mlt_consumer.c +++ b/src/framework/mlt_consumer.c @@ -77,6 +77,22 @@ int mlt_consumer_init( mlt_consumer this, void *child ) return error; } +/** Create a new consumer. +*/ + +mlt_consumer mlt_consumer_new( ) +{ + // Create the memory for the structure + mlt_consumer this = malloc( sizeof( struct mlt_consumer_s ) ); + + // Initialise it + if ( this != NULL ) + mlt_consumer_init( this, NULL ); + + // Return it + return this; +} + /** Get the parent service object. */ diff --git a/src/framework/mlt_consumer.h b/src/framework/mlt_consumer.h index bd7960d..5376756 100644 --- a/src/framework/mlt_consumer.h +++ b/src/framework/mlt_consumer.h @@ -54,6 +54,7 @@ struct mlt_consumer_s */ extern int mlt_consumer_init( mlt_consumer this, void *child ); +extern mlt_consumer mlt_consumer_new( ); extern mlt_service mlt_consumer_service( mlt_consumer this ); extern mlt_properties mlt_consumer_properties( mlt_consumer this ); extern int mlt_consumer_connect( mlt_consumer this, mlt_service producer ); diff --git a/src/framework/mlt_tractor.c b/src/framework/mlt_tractor.c index 2363448..16c7c50 100644 --- a/src/framework/mlt_tractor.c +++ b/src/framework/mlt_tractor.c @@ -110,9 +110,31 @@ int mlt_tractor_connect( mlt_tractor this, mlt_service producer ) return ret; } -/** Get the next frame. +static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) +{ + mlt_properties properties = mlt_frame_properties( this ); + mlt_frame frame = mlt_frame_pop_service( this ); + mlt_properties_inherit( mlt_frame_properties( frame ), properties ); + mlt_frame_get_image( frame, buffer, format, width, height, writable ); + mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL ); + mlt_properties_set_int( properties, "width", *width ); + mlt_properties_set_int( properties, "height", *height ); + mlt_properties_inherit( properties, mlt_frame_properties( frame ) ); + return 0; +} - TODO: This should be reading a pump being populated by the thread... +static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) +{ + mlt_properties properties = mlt_frame_properties( this ); + mlt_frame frame = mlt_frame_pop_audio( this ); + mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples ); + mlt_properties_set_data( properties, "audio", *buffer, 0, NULL, NULL ); + mlt_properties_set_int( properties, "frequency", *frequency ); + mlt_properties_set_int( properties, "channels", *channels ); + return 0; +} + +/** Get the next frame. */ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track ) @@ -123,10 +145,8 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra if ( track == 0 && this->producer != NULL ) { int i = 0; - int looking = 1; int done = 0; mlt_frame temp = NULL; - mlt_frame store[ 10 ]; int count = 0; // Get the properties of the parent producer @@ -141,10 +161,30 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra // If we don't have one, we're in trouble... if ( multitrack != NULL ) { + // Used to garbage collect all frames + char label[ 30 ]; + + // Get the id of the tractor + char *id = mlt_properties_get( properties, "_unique_id" ); + + // Will be used to store the frame properties object + mlt_properties frame_properties = NULL; + + // We'll store audio and video frames to use here + mlt_frame audio = NULL; + mlt_frame video = NULL; + + // Get the multitrack's producer mlt_producer target = mlt_multitrack_producer( multitrack ); mlt_producer_seek( target, mlt_producer_frame( parent ) ); mlt_producer_set_speed( target, mlt_producer_get_speed( parent ) ); + // We will create one frame and attach everything to it + *frame = mlt_frame_init( ); + + // Get the properties of the frame + frame_properties = mlt_frame_properties( *frame ); + // Loop through each of the tracks we're harvesting for ( i = 0; !done; i ++ ) { @@ -154,35 +194,32 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra // Check for last track done = mlt_properties_get_int( mlt_frame_properties( temp ), "last_track" ); - // Handle the frame - if ( done && looking ) - { - // Use this as output if we don't have one already - *frame = temp; - } - else if ( ( !mlt_frame_is_test_card( temp ) || !mlt_frame_is_test_audio( temp ) ) && looking && - mlt_producer_frame( parent ) == mlt_frame_get_position( temp ) ) - { - *frame = temp; - looking = 0; - } - else - { - // We store all other frames for now - store[ count ++ ] = temp; - } + // We store all frames with a destructor on the output frame + sprintf( label, "_%s_%d", id, count ++ ); + mlt_properties_set_data( frame_properties, label, temp, 0, ( mlt_destructor )mlt_frame_close, NULL ); + + // Pick up first video and audio frames + if ( audio == NULL && !mlt_frame_is_test_audio( temp ) ) + audio = temp; + if ( video == NULL && !mlt_frame_is_test_card( temp ) ) + video = temp; } - // Now place all the unused frames on to the properties (will be destroyed automatically) - while ( count -- ) + // Now stack callbacks + if ( audio != NULL ) { - mlt_properties frame_properties = mlt_frame_properties( *frame ); - char label[ 30 ]; - sprintf( label, "tractor_%d", count ); - while ( mlt_properties_get_data( frame_properties, label, NULL ) != NULL ) - strcat( label, "+" ); - mlt_properties_set_data( frame_properties, label, store[ count ], 0, ( mlt_destructor )mlt_frame_close, NULL ); + mlt_frame_push_audio( *frame, audio ); + ( *frame )->get_audio = producer_get_audio; + mlt_properties_inherit( mlt_frame_properties( *frame ), mlt_frame_properties( audio ) ); } + + if ( video != NULL ) + { + mlt_frame_push_service( *frame, video ); + mlt_frame_push_service( *frame, producer_get_image ); + mlt_properties_inherit( mlt_frame_properties( *frame ), mlt_frame_properties( video ) ); + } + } else if ( producer != NULL ) { diff --git a/src/modules/core/transition_composite.c b/src/modules/core/transition_composite.c index 1af94df..f8f78c9 100644 --- a/src/modules/core/transition_composite.c +++ b/src/modules/core/transition_composite.c @@ -40,6 +40,7 @@ typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, struct geometry_s { + int frame; float position; float mix; int nw; // normalised width @@ -154,14 +155,28 @@ static void geometry_calculate( struct geometry_s *output, struct geometry_s *in position = ( position - in->position ) / ( out->position - in->position ); // Calculate this frames geometry - output->nw = in->nw; - output->nh = in->nh; - output->x = in->x + ( out->x - in->x ) * position; - output->y = in->y + ( out->y - in->y ) * position; - output->w = in->w + ( out->w - in->w ) * position; - output->h = in->h + ( out->h - in->h ) * position; - output->mix = in->mix + ( out->mix - in->mix ) * position; - output->distort = in->distort; + if ( in->frame != out->frame - 1 ) + { + output->nw = in->nw; + output->nh = in->nh; + output->x = in->x + ( out->x - in->x ) * position; + output->y = in->y + ( out->y - in->y ) * position; + output->w = in->w + ( out->w - in->w ) * position; + output->h = in->h + ( out->h - in->h ) * position; + output->mix = in->mix + ( out->mix - in->mix ) * position; + output->distort = in->distort; + } + else + { + output->nw = out->nw; + output->nh = out->nh; + output->x = out->x; + output->y = out->y; + output->w = out->w; + output->h = out->h; + output->mix = out->mix; + output->distort = out->distort; + } // DRD> These break on negative values. I do not think they are needed // since yuv_composite takes care of YUYV group alignment @@ -239,7 +254,8 @@ static struct geometry_s *transition_parse_keys( mlt_transition this, int norma // Parse and add to the list geometry_parse( temp, ptr, value, normalised_width, normalised_height ); - // Assign the position + // Assign the position and frame + temp->frame = frame; temp->position = position; // Allow the next to be appended after this one diff --git a/src/modules/resample/filter_resample.c b/src/modules/resample/filter_resample.c index adfe067..2c848a8 100644 --- a/src/modules/resample/filter_resample.c +++ b/src/modules/resample/filter_resample.c @@ -149,24 +149,27 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) { - mlt_properties properties = mlt_filter_properties( this ); - mlt_properties frame_props = mlt_frame_properties( frame ); - - // Propogate the frequency property if supplied - if ( mlt_properties_get( properties, "frequency" ) != NULL ) - mlt_properties_set_int( frame_props, "resample.frequency", mlt_properties_get_int( properties, "frequency" ) ); - - // Propogate the other properties - mlt_properties_set_int( frame_props, "resample.channels", mlt_properties_get_int( properties, "channels" ) ); - mlt_properties_set_data( frame_props, "resample.state", mlt_properties_get_data( properties, "state", NULL ), 0, NULL, NULL ); - mlt_properties_set_data( frame_props, "resample.input_buffer", mlt_properties_get_data( properties, "input_buffer", NULL ), 0, NULL, NULL ); - mlt_properties_set_data( frame_props, "resample.output_buffer", mlt_properties_get_data( properties, "output_buffer", NULL ), 0, NULL, NULL ); + if ( frame->get_audio != NULL ) + { + mlt_properties properties = mlt_filter_properties( this ); + mlt_properties frame_props = mlt_frame_properties( frame ); + + // Propogate the frequency property if supplied + if ( mlt_properties_get( properties, "frequency" ) != NULL ) + mlt_properties_set_int( frame_props, "resample.frequency", mlt_properties_get_int( properties, "frequency" ) ); + + // Propogate the other properties + mlt_properties_set_int( frame_props, "resample.channels", mlt_properties_get_int( properties, "channels" ) ); + mlt_properties_set_data( frame_props, "resample.state", mlt_properties_get_data( properties, "state", NULL ), 0, NULL, NULL ); + mlt_properties_set_data( frame_props, "resample.input_buffer", mlt_properties_get_data( properties, "input_buffer", NULL ), 0, NULL, NULL ); + mlt_properties_set_data( frame_props, "resample.output_buffer", mlt_properties_get_data( properties, "output_buffer", NULL ), 0, NULL, NULL ); - // Backup the original get_audio (it's still needed) - mlt_properties_set_data( frame_props, "resample.get_audio", frame->get_audio, 0, NULL, NULL ); + // Backup the original get_audio (it's still needed) + mlt_properties_set_data( frame_props, "resample.get_audio", frame->get_audio, 0, NULL, NULL ); - // Override the get_audio method - frame->get_audio = resample_get_audio; + // Override the get_audio method + frame->get_audio = resample_get_audio; + } return frame; } -- 1.7.4.4