X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fframework%2Fmlt_tractor.c;h=236344859fe8353c23f064b504dae5f14b1b0096;hb=acebb83a8ead55799505891f9a95be4eead9eb49;hp=f4b77c460c98a4e85c88859b896fe992478a9e47;hpb=661165812e3410fe2f6f49d7af882b36a0efcf82;p=melted diff --git a/src/framework/mlt_tractor.c b/src/framework/mlt_tractor.c index f4b77c4..2363448 100644 --- a/src/framework/mlt_tractor.c +++ b/src/framework/mlt_tractor.c @@ -22,23 +22,26 @@ #include "mlt_tractor.h" #include "mlt_frame.h" +#include "mlt_multitrack.h" #include #include +#include /** Private structure. */ struct mlt_tractor_s { - struct mlt_service_s parent; + struct mlt_producer_s parent; mlt_service producer; }; /** Forward references to static methods. */ -static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int track ); +static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int track ); +static void producer_close( mlt_producer this ); /** Constructor for the tractor. @@ -50,10 +53,15 @@ mlt_tractor mlt_tractor_init( ) mlt_tractor this = calloc( sizeof( struct mlt_tractor_s ), 1 ); if ( this != NULL ) { - mlt_service service = &this->parent; - if ( mlt_service_init( service, this ) == 0 ) + mlt_producer producer = &this->parent; + if ( mlt_producer_init( producer, this ) == 0 ) { - service->get_frame = service_get_frame; + mlt_properties_set( mlt_producer_properties( producer ), "resource", "" ); + mlt_properties_set( mlt_producer_properties( producer ), "mlt_type", "mlt_producer" ); + mlt_properties_set( mlt_producer_properties( producer ), "mlt_service", "tractor" ); + + producer->get_frame = producer_get_frame; + producer->close = producer_close; } else { @@ -69,21 +77,35 @@ mlt_tractor mlt_tractor_init( ) mlt_service mlt_tractor_service( mlt_tractor this ) { + return mlt_producer_service( &this->parent ); +} + +/** Get the producer object associated to the tractor. +*/ + +mlt_producer mlt_tractor_producer( mlt_tractor this ) +{ return &this->parent; } +/** Get the properties object associated to the tractor. +*/ + +mlt_properties mlt_tractor_properties( mlt_tractor this ) +{ + return mlt_producer_properties( &this->parent ); +} + /** Connect the tractor. */ int mlt_tractor_connect( mlt_tractor this, mlt_service producer ) { - int ret = mlt_service_connect_producer( &this->parent, producer, 0 ); + int ret = mlt_service_connect_producer( mlt_tractor_service( this ), producer, 0 ); + // This is the producer we're going to connect to if ( ret == 0 ) - { - // This is the producer we're going to connect to this->producer = producer; - } return ret; } @@ -93,7 +115,7 @@ int mlt_tractor_connect( mlt_tractor this, mlt_service producer ) TODO: This should be reading a pump being populated by the thread... */ -static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track ) +static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track ) { mlt_tractor this = parent->child; @@ -103,35 +125,79 @@ static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track int i = 0; int looking = 1; int done = 0; - mlt_frame temp; + mlt_frame temp = NULL; + mlt_frame store[ 10 ]; + int count = 0; - // Loop through each of the tracks we're harvesting - for ( i = 0; !done; i ++ ) - { - // Get a frame from the producer - mlt_service_get_frame( this->producer, &temp, i ); + // Get the properties of the parent producer + mlt_properties properties = mlt_producer_properties( parent ); - // Check for last track - done = mlt_properties_get_int( mlt_frame_properties( temp ), "last_track" ); + // Try to obtain the multitrack associated to the tractor + mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL ); - // 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 ) && looking ) + // Or a specific producer + mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL ); + + // If we don't have one, we're in trouble... + if ( multitrack != NULL ) + { + 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 ) ); + + // Loop through each of the tracks we're harvesting + for ( i = 0; !done; i ++ ) { - // This is the one we want and we can stop looking - *frame = temp; - looking = 0; + // Get a frame from the producer + mlt_service_get_frame( this->producer, &temp, i ); + + // 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; + } } - else + + // Now place all the unused frames on to the properties (will be destroyed automatically) + while ( count -- ) { - // We discard all other frames - mlt_frame_close( temp ); + 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 ); } } + else if ( producer != NULL ) + { + mlt_producer_seek( producer, mlt_producer_frame( parent ) ); + mlt_producer_set_speed( producer, mlt_producer_get_speed( parent ) ); + mlt_service_get_frame( this->producer, frame, track ); + } + else + { + fprintf( stderr, "tractor without a multitrack!!\n" ); + mlt_service_get_frame( this->producer, frame, track ); + } + + // Prepare the next frame + mlt_producer_prepare_next( parent ); // Indicate our found status return 0; @@ -149,7 +215,16 @@ static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track void mlt_tractor_close( mlt_tractor this ) { - mlt_service_close( &this->parent ); + this->parent.close = NULL; + mlt_producer_close( &this->parent ); free( this ); } +/** Close the producer. +*/ + +static void producer_close( mlt_producer this ) +{ + mlt_tractor_close( this->child ); +} +