From 7c518e80321a87a22d2e48835442c9f5b70dcd17 Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Wed, 14 Jan 2004 11:44:44 +0000 Subject: [PATCH] Removal of timecodes, consumer libdv, serialisation of inigo git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@74 d19143bc-622f-0410-bfdd-b5b2a6649095 --- docs/testing-20040110.txt | 2 - mlt/docs/testing-20040110.txt | 2 - mlt/src/framework/mlt_consumer.c | 11 +- mlt/src/framework/mlt_factory.c | 93 +++++--- mlt/src/framework/mlt_field.c | 8 + mlt/src/framework/mlt_field.h | 1 + mlt/src/framework/mlt_filter.c | 26 +- mlt/src/framework/mlt_filter.h | 6 +- mlt/src/framework/mlt_frame.c | 16 +- mlt/src/framework/mlt_frame.h | 4 +- mlt/src/framework/mlt_multitrack.c | 32 ++-- mlt/src/framework/mlt_multitrack.h | 2 +- mlt/src/framework/mlt_playlist.c | 133 +++++------ mlt/src/framework/mlt_playlist.h | 22 +- mlt/src/framework/mlt_producer.c | 129 ++++------- mlt/src/framework/mlt_producer.h | 22 +- mlt/src/framework/mlt_properties.c | 8 +- mlt/src/framework/mlt_properties.h | 4 +- mlt/src/framework/mlt_property.c | 42 ++-- mlt/src/framework/mlt_property.h | 8 +- mlt/src/framework/mlt_tractor.c | 59 ++++- mlt/src/framework/mlt_tractor.h | 2 + mlt/src/framework/mlt_transition.c | 30 ++-- mlt/src/framework/mlt_transition.h | 6 +- mlt/src/framework/mlt_types.h | 2 +- mlt/src/inigo/inigo.c | 32 ++- mlt/src/miracle/miracle_unit.c | 35 ++-- mlt/src/modules/core/producer_ppm.c | 2 +- mlt/src/modules/core/transition_composite.c | 62 +++-- mlt/src/modules/core/transition_luma.c | 6 +- mlt/src/modules/dv/Makefile | 3 +- mlt/src/modules/dv/configure | 4 + mlt/src/modules/dv/consumer_libdv.c | 329 +++++++++++++++++++++++++++ mlt/src/modules/dv/consumer_libdv.h | 28 +++ mlt/src/modules/dv/factory.c | 3 + mlt/src/modules/dv/producer_libdv.c | 9 +- mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c | 8 +- mlt/src/modules/ffmpeg/producer_ffmpeg.c | 8 +- mlt/src/modules/gtk2/producer_pango.c | 2 +- mlt/src/modules/gtk2/producer_pixbuf.c | 8 +- mlt/src/modules/inigo/producer_inigo.c | 9 +- mlt/src/modules/sdl/consumer_sdl.c | 3 +- src/framework/mlt_consumer.c | 11 +- src/framework/mlt_factory.c | 93 +++++--- src/framework/mlt_field.c | 8 + src/framework/mlt_field.h | 1 + src/framework/mlt_filter.c | 26 +- src/framework/mlt_filter.h | 6 +- src/framework/mlt_frame.c | 16 +- src/framework/mlt_frame.h | 4 +- src/framework/mlt_multitrack.c | 32 ++-- src/framework/mlt_multitrack.h | 2 +- src/framework/mlt_playlist.c | 133 +++++------ src/framework/mlt_playlist.h | 22 +- src/framework/mlt_producer.c | 129 ++++------- src/framework/mlt_producer.h | 22 +- src/framework/mlt_properties.c | 8 +- src/framework/mlt_properties.h | 4 +- src/framework/mlt_property.c | 42 ++-- src/framework/mlt_property.h | 8 +- src/framework/mlt_tractor.c | 59 ++++- src/framework/mlt_tractor.h | 2 + src/framework/mlt_transition.c | 30 ++-- src/framework/mlt_transition.h | 6 +- src/framework/mlt_types.h | 2 +- src/inigo/inigo.c | 32 ++- src/miracle/miracle_unit.c | 35 ++-- src/modules/core/producer_ppm.c | 2 +- src/modules/core/transition_composite.c | 62 +++-- src/modules/core/transition_luma.c | 6 +- src/modules/dv/Makefile | 3 +- src/modules/dv/configure | 4 + src/modules/dv/consumer_libdv.c | 329 +++++++++++++++++++++++++++ src/modules/dv/consumer_libdv.h | 28 +++ src/modules/dv/factory.c | 3 + src/modules/dv/producer_libdv.c | 9 +- src/modules/ffmpeg/filter_ffmpeg_dub.c | 8 +- src/modules/ffmpeg/producer_ffmpeg.c | 8 +- src/modules/gtk2/producer_pango.c | 2 +- src/modules/gtk2/producer_pixbuf.c | 8 +- src/modules/inigo/producer_inigo.c | 9 +- src/modules/sdl/consumer_sdl.c | 3 +- 82 files changed, 1660 insertions(+), 778 deletions(-) create mode 100644 mlt/src/modules/dv/consumer_libdv.c create mode 100644 mlt/src/modules/dv/consumer_libdv.h create mode 100644 src/modules/dv/consumer_libdv.c create mode 100644 src/modules/dv/consumer_libdv.h diff --git a/docs/testing-20040110.txt b/docs/testing-20040110.txt index 235fd72..16c41fa 100644 --- a/docs/testing-20040110.txt +++ b/docs/testing-20040110.txt @@ -26,10 +26,8 @@ Incorrect Behaviour killall miracle does not work. requires killall -HUP STOP does not play the test card (white silence) (=pause) USTA when stopped reports "paused" -REW when stopped does not rewind to the beginning of the clip. CLEAN removes all clips (as opposed to leaving the currently playing one) USET eof=pause is partially supported -SIN/SOUT do not leave the unit in a paused state Different Intentional Behaviour diff --git a/mlt/docs/testing-20040110.txt b/mlt/docs/testing-20040110.txt index 235fd72..16c41fa 100644 --- a/mlt/docs/testing-20040110.txt +++ b/mlt/docs/testing-20040110.txt @@ -26,10 +26,8 @@ Incorrect Behaviour killall miracle does not work. requires killall -HUP STOP does not play the test card (white silence) (=pause) USTA when stopped reports "paused" -REW when stopped does not rewind to the beginning of the clip. CLEAN removes all clips (as opposed to leaving the currently playing one) USET eof=pause is partially supported -SIN/SOUT do not leave the unit in a paused state Different Intentional Behaviour diff --git a/mlt/src/framework/mlt_consumer.c b/mlt/src/framework/mlt_consumer.c index f263a20..5ff7f5f 100644 --- a/mlt/src/framework/mlt_consumer.c +++ b/mlt/src/framework/mlt_consumer.c @@ -63,8 +63,15 @@ int mlt_consumer_connect( mlt_consumer this, mlt_service producer ) void mlt_consumer_close( mlt_consumer this ) { - if ( this->close != NULL ) - this->close( this ); + // Get the childs close function + void ( *consumer_close )( ) = this->close; + + // Make sure it only gets called once + this->close = NULL; + + // Call the childs close if available + if ( consumer_close != NULL ) + consumer_close( this ); else mlt_service_close( &this->parent ); } diff --git a/mlt/src/framework/mlt_factory.c b/mlt/src/framework/mlt_factory.c index 9795770..9223178 100644 --- a/mlt/src/framework/mlt_factory.c +++ b/mlt/src/framework/mlt_factory.c @@ -19,9 +19,8 @@ */ #include "config.h" -#include "mlt_factory.h" +#include "mlt.h" #include "mlt_repository.h" -#include "mlt_properties.h" #include #include @@ -41,22 +40,26 @@ static mlt_repository consumers = NULL; int mlt_factory_init( char *prefix ) { - // If no directory is specified, default to install directory - if ( prefix == NULL ) - prefix = PREFIX_DATA; - - // Store the prefix for later retrieval - mlt_prefix = strdup( prefix ); - - // Create the object list. - object_list = calloc( sizeof( struct mlt_properties_s ), 1 ); - mlt_properties_init( object_list, NULL ); - - // Create a repository for each service type - producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" ); - filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" ); - transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" ); - consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" ); + // Only initialise once + if ( mlt_prefix == NULL ) + { + // If no directory is specified, default to install directory + if ( prefix == NULL ) + prefix = PREFIX_DATA; + + // Store the prefix for later retrieval + mlt_prefix = strdup( prefix ); + + // Create the object list. + object_list = calloc( sizeof( struct mlt_properties_s ), 1 ); + mlt_properties_init( object_list, NULL ); + + // Create a repository for each service type + producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" ); + filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" ); + transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" ); + consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" ); + } return 0; } @@ -74,7 +77,14 @@ const char *mlt_factory_prefix( ) mlt_producer mlt_factory_producer( char *service, void *input ) { - return ( mlt_producer )mlt_repository_fetch( producers, service, input ); + mlt_producer obj = mlt_repository_fetch( producers, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_producer_properties( obj ); + mlt_properties_set( properties, "mlt_type", "producer" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Fetch a filter from the repository. @@ -82,7 +92,14 @@ mlt_producer mlt_factory_producer( char *service, void *input ) mlt_filter mlt_factory_filter( char *service, void *input ) { - return ( mlt_filter )mlt_repository_fetch( filters, service, input ); + mlt_filter obj = mlt_repository_fetch( filters, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_filter_properties( obj ); + mlt_properties_set( properties, "mlt_type", "filter" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Fetch a transition from the repository. @@ -90,7 +107,14 @@ mlt_filter mlt_factory_filter( char *service, void *input ) mlt_transition mlt_factory_transition( char *service, void *input ) { - return ( mlt_transition )mlt_repository_fetch( transitions, service, input ); + mlt_transition obj = mlt_repository_fetch( transitions, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_transition_properties( obj ); + mlt_properties_set( properties, "mlt_type", "transition" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Fetch a consumer from the repository @@ -98,7 +122,14 @@ mlt_transition mlt_factory_transition( char *service, void *input ) mlt_consumer mlt_factory_consumer( char *service, void *input ) { - return ( mlt_consumer )mlt_repository_fetch( consumers, service, input ); + mlt_consumer obj = mlt_repository_fetch( consumers, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_consumer_properties( obj ); + mlt_properties_set( properties, "mlt_type", "consumer" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Close the factory. @@ -106,12 +137,16 @@ mlt_consumer mlt_factory_consumer( char *service, void *input ) void mlt_factory_close( ) { - mlt_repository_close( producers ); - mlt_repository_close( filters ); - mlt_repository_close( transitions ); - mlt_repository_close( consumers ); - mlt_properties_close( object_list ); - free( mlt_prefix ); - free( object_list ); + if ( mlt_prefix != NULL ) + { + mlt_repository_close( producers ); + mlt_repository_close( filters ); + mlt_repository_close( transitions ); + mlt_repository_close( consumers ); + mlt_properties_close( object_list ); + free( mlt_prefix ); + free( object_list ); + mlt_prefix = NULL; + } } diff --git a/mlt/src/framework/mlt_field.c b/mlt/src/framework/mlt_field.c index a54d97e..8a7f51f 100644 --- a/mlt/src/framework/mlt_field.c +++ b/mlt/src/framework/mlt_field.c @@ -89,6 +89,14 @@ mlt_multitrack mlt_field_multitrack( mlt_field this ) return this->multitrack; } +/** Get the tractor. +*/ + +mlt_tractor mlt_field_tractor( mlt_field this ) +{ + return this->tractor; +} + /** Get the properties associated to this field. */ diff --git a/mlt/src/framework/mlt_field.h b/mlt/src/framework/mlt_field.h index 6fef296..d84d0cc 100644 --- a/mlt/src/framework/mlt_field.h +++ b/mlt/src/framework/mlt_field.h @@ -25,6 +25,7 @@ extern mlt_field mlt_field_init( ); extern mlt_service mlt_field_service( mlt_field this ); +extern mlt_tractor mlt_field_tractor( mlt_field this ); extern mlt_multitrack mlt_field_multitrack( mlt_field this ); extern mlt_properties mlt_field_properties( mlt_field this ); extern int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track ); diff --git a/mlt/src/framework/mlt_filter.c b/mlt/src/framework/mlt_filter.c index 9c0a295..6e39e79 100644 --- a/mlt/src/framework/mlt_filter.c +++ b/mlt/src/framework/mlt_filter.c @@ -45,8 +45,8 @@ int mlt_filter_init( mlt_filter this, void *child ) service->get_frame = filter_get_frame; // Default in, out, track properties - mlt_properties_set_timecode( properties, "in", 0 ); - mlt_properties_set_timecode( properties, "out", 0 ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", 0 ); mlt_properties_set_int( properties, "track", 0 ); return 0; @@ -80,8 +80,8 @@ int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ) { mlt_properties properties = mlt_service_properties( &this->parent ); this->producer = producer; - mlt_properties_set_timecode( properties, "in", 0 ); - mlt_properties_set_timecode( properties, "out", 0 ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", 0 ); mlt_properties_set_int( properties, "track", index ); } @@ -91,11 +91,11 @@ int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ) /** Tune the in/out points. */ -void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out ) +void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out ) { mlt_properties properties = mlt_service_properties( &this->parent ); - mlt_properties_set_timecode( properties, "in", in ); - mlt_properties_set_timecode( properties, "out", out ); + mlt_properties_set_position( properties, "in", in ); + mlt_properties_set_position( properties, "out", out ); } /** Return the track that this filter is operating on. @@ -110,19 +110,19 @@ int mlt_filter_get_track( mlt_filter this ) /** Get the in point. */ -mlt_timecode mlt_filter_get_in( mlt_filter this ) +mlt_position mlt_filter_get_in( mlt_filter this ) { mlt_properties properties = mlt_service_properties( &this->parent ); - return mlt_properties_get_timecode( properties, "in" ); + return mlt_properties_get_position( properties, "in" ); } /** Get the out point. */ -mlt_timecode mlt_filter_get_out( mlt_filter this ) +mlt_position mlt_filter_get_out( mlt_filter this ) { mlt_properties properties = mlt_service_properties( &this->parent ); - return mlt_properties_get_timecode( properties, "out" ); + return mlt_properties_get_position( properties, "out" ); } /** Process the frame. @@ -156,8 +156,8 @@ static int filter_get_frame( mlt_service service, mlt_frame_ptr frame, int index { if ( !mlt_frame_is_test_card( *frame ) ) { - mlt_timecode timecode = mlt_frame_get_timecode( *frame ); - if ( timecode >= in && ( out == 0 || timecode < out ) ) + mlt_position position = mlt_frame_get_position( *frame ); + if ( position >= in && ( out == 0 || position < out ) ) *frame = filter_process( this, *frame ); } return 0; diff --git a/mlt/src/framework/mlt_filter.h b/mlt/src/framework/mlt_filter.h index e3f0f74..edaf6f6 100644 --- a/mlt/src/framework/mlt_filter.h +++ b/mlt/src/framework/mlt_filter.h @@ -51,10 +51,10 @@ extern int mlt_filter_init( mlt_filter this, void *child ); extern mlt_service mlt_filter_service( mlt_filter this ); extern mlt_properties mlt_filter_properties( mlt_filter this ); extern int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ); -extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out ); +extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out ); extern int mlt_filter_get_track( mlt_filter this ); -extern mlt_timecode mlt_filter_get_in( mlt_filter this ); -extern mlt_timecode mlt_filter_get_out( mlt_filter this ); +extern mlt_position mlt_filter_get_in( mlt_filter this ); +extern mlt_position mlt_filter_get_out( mlt_filter this ); extern void mlt_filter_close( mlt_filter ); #endif diff --git a/mlt/src/framework/mlt_frame.c b/mlt/src/framework/mlt_frame.c index a51fb7e..cb26ee9 100644 --- a/mlt/src/framework/mlt_frame.c +++ b/mlt/src/framework/mlt_frame.c @@ -53,7 +53,7 @@ mlt_frame mlt_frame_init( ) mlt_properties_init( properties, this ); // Set default properties on the frame - mlt_properties_set_timecode( properties, "timecode", 0.0 ); + mlt_properties_set_position( properties, "position", 0.0 ); mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL ); mlt_properties_set_int( properties, "width", 720 ); mlt_properties_set_int( properties, "height", 576 ); @@ -98,22 +98,22 @@ int mlt_frame_set_aspect_ratio( mlt_frame this, double value ) return mlt_properties_set_double( properties, "aspect_ratio", value ); } -/** Get the timecode of this frame. +/** Get the position of this frame. */ -mlt_timecode mlt_frame_get_timecode( mlt_frame this ) +mlt_position mlt_frame_get_position( mlt_frame this ) { mlt_properties properties = mlt_frame_properties( this ); - return mlt_properties_get_timecode( properties, "timecode" ); + return mlt_properties_get_position( properties, "position" ); } -/** Set the timecode of this frame. +/** Set the position of this frame. */ -int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value ) +int mlt_frame_set_position( mlt_frame this, mlt_position value ) { mlt_properties properties = mlt_frame_properties( this ); - return mlt_properties_set_timecode( properties, "timecode", value ); + return mlt_properties_set_position( properties, "position", value ); } /** Stack a get_image callback. @@ -709,7 +709,7 @@ int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight, int16_t * int i, j; mlt_frame_get_audio( this, &p_dest, format, &frequency_dest, &channels_dest, &samples_dest ); - //fprintf( stderr, "frame dest samples %d channels %d timecode %f\n", samples_dest, channels_dest, mlt_properties_get_timecode( mlt_frame_properties( this ), "timecode" ) ); + //fprintf( stderr, "frame dest samples %d channels %d position %f\n", samples_dest, channels_dest, mlt_properties_get_position( mlt_frame_properties( this ), "position" ) ); mlt_frame_get_audio( that, &p_src, format, &frequency_src, &channels_src, &samples_src ); //fprintf( stderr, "frame src samples %d channels %d\n", samples_src, channels_src ); if ( channels_src > 6 ) diff --git a/mlt/src/framework/mlt_frame.h b/mlt/src/framework/mlt_frame.h index 175df0a..58476d5 100644 --- a/mlt/src/framework/mlt_frame.h +++ b/mlt/src/framework/mlt_frame.h @@ -70,8 +70,8 @@ extern mlt_properties mlt_frame_properties( mlt_frame this ); extern int mlt_frame_is_test_card( mlt_frame this ); extern double mlt_frame_get_aspect_ratio( mlt_frame this ); extern int mlt_frame_set_aspect_ratio( mlt_frame this, double value ); -extern mlt_timecode mlt_frame_get_timecode( mlt_frame this ); -extern int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value ); +extern mlt_position mlt_frame_get_position( mlt_frame this ); +extern int mlt_frame_set_position( mlt_frame this, mlt_position value ); extern int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ); extern uint8_t *mlt_frame_get_alpha_mask( mlt_frame this ); diff --git a/mlt/src/framework/mlt_multitrack.c b/mlt/src/framework/mlt_multitrack.c index 893cef5..47bc271 100644 --- a/mlt/src/framework/mlt_multitrack.c +++ b/mlt/src/framework/mlt_multitrack.c @@ -96,7 +96,7 @@ mlt_properties mlt_multitrack_properties( mlt_multitrack this ) return mlt_service_properties( mlt_multitrack_service( this ) ); } -/** Initialise timecode related information. +/** Initialise position related information. */ void mlt_multitrack_refresh( mlt_multitrack this ) @@ -107,7 +107,7 @@ void mlt_multitrack_refresh( mlt_multitrack this ) mlt_properties properties = mlt_multitrack_properties( this ); // We need to ensure that the multitrack reports the longest track as its length - mlt_timecode length = 0; + mlt_position length = 0; // We need to ensure that fps are the same on all services double fps = 0; @@ -146,8 +146,8 @@ void mlt_multitrack_refresh( mlt_multitrack this ) } // Update multitrack properties now - we'll not destroy the in point here - mlt_properties_set_timecode( properties, "length", length ); - mlt_properties_set_timecode( properties, "out", length ); + mlt_properties_set_position( properties, "length", length ); + mlt_properties_set_position( properties, "out", length ); mlt_properties_set_double( properties, "fps", fps ); } @@ -208,10 +208,10 @@ int mlt_multitrack_connect( mlt_multitrack this, mlt_producer producer, int trac 0.0, 1.0, b0.0, 0.1, b1.1, 1.1, 0.1, 0.2, [out of playlist2], [out of playlist1] */ -mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ) +mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ) { int first = 1; - mlt_timecode position = 0; + mlt_position position = 0; int i = 0; // Loop through each of the tracks @@ -232,7 +232,7 @@ mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int in // We only consider playlists if ( playlist != NULL ) { - // Locate the smallest timecode + // Locate the smallest position if ( first ) { // First position found @@ -244,13 +244,17 @@ mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int in else { // Obtain the clip position in this playlist - mlt_timecode position2 = mlt_playlist_clip( playlist, whence, index ); + //mlt_position position2 = mlt_playlist_clip( playlist, whence, index ); // If this position is prior to the first, then use it - if ( position2 < position ) - position = position2; + //if ( position2 < position ) + //position = position2; } } + else + { + fprintf( stderr, "track %d isn't a playlist\n", index ); + } } } @@ -293,11 +297,11 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int ind // Get the producer for this track mlt_producer producer = this->list[ index ]; - // Obtain the current timecode + // Obtain the current position uint64_t position = mlt_producer_frame( parent ); // Make sure we're at the same point - mlt_producer_seek_frame( producer, position ); + mlt_producer_seek( producer, position ); // Get the frame from the producer mlt_service_get_frame( mlt_producer_service( producer ), frame, 0 ); @@ -313,8 +317,8 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int ind // Generate a test frame *frame = mlt_frame_init( ); - // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( parent ) ); + // Update position on the frame we're creating + mlt_frame_set_position( *frame, mlt_producer_position( parent ) ); // Move on to the next frame if ( index >= this->count ) diff --git a/mlt/src/framework/mlt_multitrack.h b/mlt/src/framework/mlt_multitrack.h index 83f34dd..3f6d8d9 100644 --- a/mlt/src/framework/mlt_multitrack.h +++ b/mlt/src/framework/mlt_multitrack.h @@ -31,7 +31,7 @@ extern mlt_producer mlt_multitrack_producer( mlt_multitrack this ); extern mlt_service mlt_multitrack_service( mlt_multitrack this ); extern mlt_properties mlt_multitrack_properties( mlt_multitrack this ); extern int mlt_multitrack_connect( mlt_multitrack this, mlt_producer producer, int track ); -extern mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ); +extern mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ); extern void mlt_multitrack_close( mlt_multitrack this ); #endif diff --git a/mlt/src/framework/mlt_playlist.c b/mlt/src/framework/mlt_playlist.c index 519585c..921bbd5 100644 --- a/mlt/src/framework/mlt_playlist.c +++ b/mlt/src/framework/mlt_playlist.c @@ -33,10 +33,9 @@ typedef struct { mlt_producer producer; - int64_t frame_in; - int64_t frame_out; - int64_t frame_count; - mlt_timecode playtime; + mlt_position frame_in; + mlt_position frame_out; + mlt_position frame_count; } playlist_entry; @@ -111,13 +110,16 @@ mlt_properties mlt_playlist_properties( mlt_playlist this ) return mlt_producer_properties( &this->parent ); } +/** Refresh the playlist after a clip has been changed. +*/ + static int mlt_playlist_virtual_refresh( mlt_playlist this ) { int i = 0; // Get the fps of the first producer double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "first_fps" ); - mlt_timecode playtime = 0; + mlt_position frame_count = 0; for ( i = 0; i < this->count; i ++ ) { @@ -139,15 +141,15 @@ static int mlt_playlist_virtual_refresh( mlt_playlist this ) mlt_properties_set_double( mlt_producer_properties( producer ), "fps", fps ); } - // Update the playtime for this clip - playtime += this->list[ i ]->playtime; + // Update the frame_count for this clip + frame_count += this->list[ i ]->frame_count; } // Refresh all properties mlt_properties_set_double( mlt_playlist_properties( this ), "first_fps", fps ); mlt_properties_set_double( mlt_playlist_properties( this ), "fps", fps == 0 ? 25 : fps ); - mlt_properties_set_timecode( mlt_playlist_properties( this ), "length", playtime ); - mlt_properties_set_timecode( mlt_playlist_properties( this ), "out", playtime ); + mlt_properties_set_position( mlt_playlist_properties( this ), "length", frame_count ); + mlt_properties_set_position( mlt_playlist_properties( this ), "out", frame_count ); return 0; } @@ -155,11 +157,8 @@ static int mlt_playlist_virtual_refresh( mlt_playlist this ) /** Append to the virtual playlist. */ -static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, int64_t in, int64_t out ) +static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out ) { - double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "fps" ); - double playtime = ( double )( out - in + 1 ) / fps; - // Check that we have room if ( this->count >= this->size ) { @@ -175,7 +174,6 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer this->list[ this->count ]->frame_in = in; this->list[ this->count ]->frame_out = out; this->list[ this->count ]->frame_count = out - in + 1; - this->list[ this->count ]->playtime = playtime; mlt_producer_set_speed( producer, 0 ); @@ -193,21 +191,27 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) mlt_producer producer = NULL; // Map playlist position to real producer in virtual playlist - mlt_timecode pos = mlt_producer_position( &this->parent ); - int64_t position = mlt_producer_frame_position( &this->parent, pos ); + mlt_position position = mlt_producer_frame( &this->parent ); + + // Total number of frames int64_t total = 0; + // Get the properties mlt_properties properties = mlt_playlist_properties( this ); + + // Get the eof handling char *eof = mlt_properties_get( properties, "eof" ); - // Loop through the virtual playlist + // Index for the main loop int i = 0; + // Loop for each producer until found for ( i = 0; i < this->count; i ++ ) { // Increment the total total += this->list[ i ]->frame_count; + // Check if the position indicates that we have found the clip if ( position < this->list[ i ]->frame_count ) { // Found it, now break @@ -225,47 +229,43 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) if ( producer != NULL ) { position += this->list[ i ]->frame_in; - position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - mlt_producer_seek_frame( producer, position ); + mlt_producer_seek( producer, position ); } else if ( !strcmp( eof, "pause" ) && total > 0 ) { playlist_entry *entry = this->list[ this->count - 1 ]; mlt_producer this_producer = mlt_playlist_producer( this ); - mlt_producer_seek_frame( this_producer, total - 1 ); + mlt_producer_seek( this_producer, total - 1 - mlt_producer_get_in( this_producer ) ); producer = entry->producer; - position = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - mlt_producer_seek_frame( producer, position + entry->frame_out ); + mlt_producer_seek( producer, entry->frame_out ); mlt_producer_set_speed( this_producer, 0 ); - mlt_producer_set_speed( producer, 0 ); } else if ( !strcmp( eof, "loop" ) && total > 0 ) { playlist_entry *entry = this->list[ 0 ]; mlt_producer this_producer = mlt_playlist_producer( this ); - mlt_producer_seek_frame( this_producer, 0 ); + mlt_producer_seek( this_producer, 0 ); producer = entry->producer; - position = entry->frame_in; - position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - mlt_producer_seek_frame( producer, position ); + mlt_producer_seek( producer, entry->frame_in ); } else { - mlt_producer_seek( mlt_playlist_producer( this ), 0 ); producer = &this->blank; } return producer; } +/** Invoked when a producer indicates that it has prematurely reached its end. +*/ + static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this ) { // Default producer to blank mlt_producer producer = &this->blank; // Map playlist position to real producer in virtual playlist - mlt_timecode pos = mlt_producer_position( &this->parent ); - int64_t position = mlt_producer_frame_position( &this->parent, pos ); + mlt_position position = mlt_producer_frame( &this->parent ); // Loop through the virtual playlist int i = 0; @@ -288,9 +288,9 @@ static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this ) // Seek in real producer to relative position if ( i < this->count ) { - // Update the playtime for the changed clip (hmmm) - this->list[ i ]->frame_count = position + 1; - this->list[ i ]->frame_out = position - this->list[ i ]->frame_in; + // Update the frame_count for the changed clip (hmmm) + this->list[ i ]->frame_out = position; + this->list[ i ]->frame_count = this->list[ i ]->frame_out - this->list[ i ]->frame_in + 1; // Refresh the playlist mlt_playlist_virtual_refresh( this ); @@ -299,11 +299,13 @@ static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this ) return producer; } +/** Obtain the current clips index. +*/ + int mlt_playlist_current_clip( mlt_playlist this ) { // Map playlist position to real producer in virtual playlist - mlt_timecode pos = mlt_producer_position( &this->parent ); - int64_t position = mlt_producer_frame_position( &this->parent, pos ); + mlt_position position = mlt_producer_frame( &this->parent ); // Loop through the virtual playlist int i = 0; @@ -325,6 +327,9 @@ int mlt_playlist_current_clip( mlt_playlist this ) return i; } +/** Obtain the current clips producer. +*/ + mlt_producer mlt_playlist_current( mlt_playlist this ) { int i = mlt_playlist_current_clip( this ); @@ -334,10 +339,10 @@ mlt_producer mlt_playlist_current( mlt_playlist this ) return &this->blank; } -/** Get the timecode which corresponds to the start of the next clip. +/** Get the position which corresponds to the start of the next clip. */ -mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ) +mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ) { int64_t position = 0; int absolute_clip = index; @@ -365,11 +370,11 @@ mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index else if ( absolute_clip > this->count ) absolute_clip = this->count; - // Now determine the timecode + // Now determine the position for ( i = 0; i < absolute_clip; i ++ ) position += this->list[ i ]->frame_count; - return mlt_producer_time( &this->parent, position ); + return position; } int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index ) @@ -384,10 +389,8 @@ int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, info->start = mlt_playlist_clip( this, mlt_whence_relative_start, index ); info->resource = mlt_properties_get( properties, "resource" ); info->frame_in = this->list[ index ]->frame_in; - info->in = mlt_producer_time( producer, info->frame_in ); info->frame_out = this->list[ index ]->frame_out; - info->out = mlt_producer_time( producer, info->frame_out ); - info->playtime = this->list[ index ]->playtime; + info->frame_count = this->list[ index ]->frame_count; info->length = mlt_producer_get_length( producer ); info->fps = mlt_producer_get_fps( producer ); } @@ -418,43 +421,34 @@ int mlt_playlist_clear( mlt_playlist this ) int mlt_playlist_append( mlt_playlist this, mlt_producer producer ) { // Append to virtual list - int64_t in = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - int64_t out = mlt_producer_frame_position( producer, mlt_producer_get_out( producer ) ); - return mlt_playlist_virtual_append( this, producer, 0, out - in ); + return mlt_playlist_virtual_append( this, producer, 0, mlt_producer_get_playtime( producer ) - 1 ); } /** Append a producer to the playlist with in/out points. */ -int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out ) +int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out ) { // Append to virtual list if ( in != -1 && out != -1 ) - { - int64_t fin = mlt_producer_frame_position( producer, in ); - int64_t fout = mlt_producer_frame_position( producer, out ); - return mlt_playlist_virtual_append( this, producer, fin, fout ); - } + return mlt_playlist_virtual_append( this, producer, in, out ); else - { return mlt_playlist_append( this, producer ); - } } /** Append a blank to the playlist of a given length. */ -int mlt_playlist_blank( mlt_playlist this, mlt_timecode length ) +int mlt_playlist_blank( mlt_playlist this, mlt_position length ) { // Append to the virtual list - int64_t fout = mlt_producer_frame_position( &this->blank, length ); - return mlt_playlist_virtual_append( this, &this->blank, 0, fout ); + return mlt_playlist_virtual_append( this, &this->blank, 0, length ); } /** Insert a producer into the playlist. */ -int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out ) +int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out ) { return 0; } @@ -469,7 +463,10 @@ int mlt_playlist_move( mlt_playlist this, int from, int to ) return 0; } -int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out ) +/** Resize the current clip. +*/ + +int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out ) { int error = clip < 0 || clip >= this->count; if ( error == 0 ) @@ -479,23 +476,19 @@ int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_ if ( in <= -1 ) in = 0; - if ( out <= -1 || out >= mlt_producer_get_out( producer ) ) - out = mlt_producer_get_out( producer ); + if ( out <= -1 || out >= mlt_producer_get_playtime( producer ) ) + out = mlt_producer_get_playtime( producer ) - 1; if ( out < in ) { - mlt_timecode t = in; + mlt_position t = in; in = out; out = t; } - int64_t fin = mlt_producer_frame_position( producer, in ); - int64_t fout = mlt_producer_frame_position( producer, out ); - - entry->frame_in = fin; - entry->frame_out = fout; - entry->frame_count = fout - fin + 1; - entry->playtime = out - in; + entry->frame_in = in; + entry->frame_out = out; + entry->frame_count = out - in + 1; mlt_playlist_virtual_refresh( this ); } return error; @@ -529,8 +522,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i notifier( argument ); } - // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + // Update position on the frame we're creating + mlt_frame_set_position( *frame, mlt_producer_frame( producer ) ); // Position ourselves on the next frame mlt_producer_prepare_next( producer ); diff --git a/mlt/src/framework/mlt_playlist.h b/mlt/src/framework/mlt_playlist.h index 8cdccce..dd88959 100644 --- a/mlt/src/framework/mlt_playlist.h +++ b/mlt/src/framework/mlt_playlist.h @@ -29,14 +29,12 @@ typedef struct { mlt_producer producer; - mlt_timecode start; + mlt_position start; char *resource; - mlt_timecode in; - int64_t frame_in; - mlt_timecode out; - int64_t frame_out; - mlt_timecode playtime; - mlt_timecode length; + mlt_position frame_in; + mlt_position frame_out; + mlt_position frame_count; + mlt_position length; float fps; } mlt_playlist_clip_info; @@ -51,16 +49,16 @@ extern mlt_properties mlt_playlist_properties( mlt_playlist this ); extern int mlt_playlist_count( mlt_playlist this ); extern int mlt_playlist_clear( mlt_playlist this ); extern int mlt_playlist_append( mlt_playlist this, mlt_producer producer ); -extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out ); -extern int mlt_playlist_blank( mlt_playlist this, mlt_timecode length ); -extern mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ); +extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out ); +extern int mlt_playlist_blank( mlt_playlist this, mlt_position length ); +extern mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ); extern int mlt_playlist_current_clip( mlt_playlist this ); extern mlt_producer mlt_playlist_current( mlt_playlist this ); extern int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index ); -extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out ); +extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out ); extern int mlt_playlist_remove( mlt_playlist this, int where ); extern int mlt_playlist_move( mlt_playlist this, int from, int to ); -extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out ); +extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out ); extern void mlt_playlist_close( mlt_playlist this ); #endif diff --git a/mlt/src/framework/mlt_producer.c b/mlt/src/framework/mlt_producer.c index 278d902..c874243 100644 --- a/mlt/src/framework/mlt_producer.c +++ b/mlt/src/framework/mlt_producer.c @@ -53,14 +53,13 @@ int mlt_producer_init( mlt_producer this, void *child ) // Set the default properties mlt_properties_set( properties, "mlt_type", "mlt_producer" ); - mlt_properties_set_timecode( properties, "position", 0.0 ); + mlt_properties_set_position( properties, "position", 0.0 ); mlt_properties_set_double( properties, "frame", 0 ); mlt_properties_set_double( properties, "fps", 25.0 ); mlt_properties_set_double( properties, "speed", 1.0 ); - mlt_properties_set_timecode( properties, "in", 0.0 ); - mlt_properties_set_timecode( properties, "out", 36000.0 ); - mlt_properties_set_timecode( properties, "length", 36000.0 ); - mlt_properties_set_int( properties, "known_length", 1 ); + mlt_properties_set_position( properties, "in", 0.0 ); + mlt_properties_set_position( properties, "out", 179999 ); + mlt_properties_set_position( properties, "length", 180000 ); mlt_properties_set_double( properties, "aspect_ratio", 4.0 / 3.0 ); mlt_properties_set( properties, "log_id", "multitrack" ); @@ -87,92 +86,64 @@ mlt_properties mlt_producer_properties( mlt_producer this ) return mlt_service_properties( &this->parent ); } -/** Convert frame position to timecode. +/** Convert frame position to position. */ -mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame ) +/* +mlt_position mlt_producer_time( mlt_producer this, int64_t frame ) { if ( frame < 0 ) return -1; else - return ( mlt_timecode )frame / mlt_producer_get_fps( this ); + return ( mlt_position )frame / mlt_producer_get_fps( this ); } +*/ -/** Convert timecode to frame position. +/** Convert position to frame position. */ -int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position ) +/* +int64_t mlt_producer_frame_position( mlt_producer this, mlt_position position ) { if ( position < 0 ) return -1; else return ( int64_t )( floor( position * mlt_producer_get_fps( this ) + 0.5 ) ); } +*/ -/** Seek to a specified time code. +/** Seek to a specified position. */ -int mlt_producer_seek( mlt_producer this, mlt_timecode timecode ) +int mlt_producer_seek( mlt_producer this, mlt_position position ) { // Check bounds - if ( timecode < 0 ) - timecode = 0; - if ( timecode > mlt_producer_get_playtime( this ) ) - timecode = mlt_producer_get_playtime( this ); + if ( position < 0 ) + position = 0; + else if ( position > mlt_producer_get_playtime( this ) ) + position = mlt_producer_get_playtime( this ) - 1; // Set the position - mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode ); + mlt_properties_set_position( mlt_producer_properties( this ), "position", position ); // Calculate the absolute frame - double frame = ( mlt_producer_get_in( this ) + timecode ) * mlt_producer_get_fps( this ); - mlt_properties_set_double( mlt_producer_properties( this ), "frame", floor( frame + 0.5 ) ); - - return 0; -} - -/** Seek to a specified absolute frame. -*/ - -int mlt_producer_seek_frame( mlt_producer this, int64_t frame ) -{ - // Calculate the time code - double timecode = ( frame / mlt_producer_get_fps( this ) ) - mlt_producer_get_in( this ); - - // If timecode is invalid, then seek on time - if ( frame < 0 || timecode < 0 ) - { - // Seek to the in point - mlt_producer_seek( this, 0 ); - } - else if ( timecode > mlt_producer_get_playtime( this ) ) - { - // Seek to the out point - mlt_producer_seek( this, mlt_producer_get_playtime( this ) ); - } - else - { - // Set the position - mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode ); - - // Set the absolute frame - mlt_properties_set_double( mlt_producer_properties( this ), "frame", frame ); - } + mlt_properties_set_position( mlt_producer_properties( this ), "frame", mlt_producer_get_in( this ) + position ); return 0; } -/** Get the current time code. +/** Get the current position (relative to in point). */ -mlt_timecode mlt_producer_position( mlt_producer this ) +mlt_position mlt_producer_position( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "position" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "position" ); } -/** Get the current frame. +/** Get the current position (relative to start of producer). */ -uint64_t mlt_producer_frame( mlt_producer this ) +mlt_position mlt_producer_frame( mlt_producer this ) { return mlt_properties_get_double( mlt_producer_properties( this ), "frame" ); } @@ -204,32 +175,30 @@ double mlt_producer_get_fps( mlt_producer this ) /** Set the in and out points. */ -int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out ) +int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out ) { // Correct ins and outs if necessary if ( in < 0 ) in = 0; - if ( in > mlt_producer_get_length( this ) ) + else if ( in > mlt_producer_get_length( this ) ) in = mlt_producer_get_length( this ); + if ( out < 0 ) out = 0; - if ( out > mlt_producer_get_length( this ) ) + else if ( out > mlt_producer_get_length( this ) ) out = mlt_producer_get_length( this ); // Swap ins and outs if wrong if ( out < in ) { - mlt_timecode t = in; + mlt_position t = in; in = out; out = t; } // Set the values - mlt_properties_set_timecode( mlt_producer_properties( this ), "in", in ); - mlt_properties_set_timecode( mlt_producer_properties( this ), "out", out ); - - // Seek to the in point - mlt_producer_seek( this, 0 ); + mlt_properties_set_position( mlt_producer_properties( this ), "in", in ); + mlt_properties_set_position( mlt_producer_properties( this ), "out", out ); return 0; } @@ -237,33 +206,33 @@ int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecod /** Get the in point. */ -mlt_timecode mlt_producer_get_in( mlt_producer this ) +mlt_position mlt_producer_get_in( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "in" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "in" ); } /** Get the out point. */ -mlt_timecode mlt_producer_get_out( mlt_producer this ) +mlt_position mlt_producer_get_out( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "out" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "out" ); } /** Get the total play time. */ -mlt_timecode mlt_producer_get_playtime( mlt_producer this ) +mlt_position mlt_producer_get_playtime( mlt_producer this ) { - return mlt_producer_get_out( this ) - mlt_producer_get_in( this ); + return mlt_producer_get_out( this ) - mlt_producer_get_in( this ) + 1; } /** Get the total length of the producer. */ -mlt_timecode mlt_producer_get_length( mlt_producer this ) +mlt_position mlt_producer_get_length( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "length" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "length" ); } /** Prepare for next frame. @@ -271,7 +240,7 @@ mlt_timecode mlt_producer_get_length( mlt_producer this ) void mlt_producer_prepare_next( mlt_producer this ) { - mlt_producer_seek_frame( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) ); + mlt_producer_seek( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) ); } /** Get a frame. @@ -287,26 +256,24 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind { // Get the frame from the implementation result = this->get_frame( this, frame, index ); - - mlt_properties frame_properties = mlt_frame_properties( *frame ); - double speed = mlt_producer_get_speed( this ); - mlt_properties_set_double( frame_properties, "speed", speed ); } else { // Generate a test frame *frame = mlt_frame_init( ); - // Set the timecode - result = mlt_frame_set_timecode( *frame, mlt_producer_position( this ) ); + // Set the position + result = mlt_frame_set_position( *frame, mlt_producer_position( this ) ); - // Calculate the next timecode + // Calculate the next position mlt_producer_prepare_next( this ); } - // Copy the fps of the producer onto the frame + // Copy the fps and speed of the producer onto the frame mlt_properties properties = mlt_frame_properties( *frame ); mlt_properties_set_double( properties, "fps", mlt_producer_get_fps( this ) ); + double speed = mlt_producer_get_speed( this ); + mlt_properties_set_double( properties, "speed", speed ); return 0; } diff --git a/mlt/src/framework/mlt_producer.h b/mlt/src/framework/mlt_producer.h index 5297652..7e748c0 100644 --- a/mlt/src/framework/mlt_producer.h +++ b/mlt/src/framework/mlt_producer.h @@ -43,23 +43,23 @@ struct mlt_producer_s /** Public final methods */ +//extern double mlt_producer_convert_position_to_time( mlt_producer this, int64_t frame ); +//extern mlt_position mlt_producer_convert_time_to_position( mlt_producer this, double time ); + extern int mlt_producer_init( mlt_producer this, void *child ); extern mlt_service mlt_producer_service( mlt_producer this ); extern mlt_properties mlt_producer_properties( mlt_producer this ); -extern mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame ); -extern int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position ); -extern int mlt_producer_seek( mlt_producer this, mlt_timecode timecode ); -extern int mlt_producer_seek_frame( mlt_producer this, int64_t frame ); -extern mlt_timecode mlt_producer_position( mlt_producer this ); -extern uint64_t mlt_producer_frame( mlt_producer this ); +extern int mlt_producer_seek( mlt_producer this, mlt_position position ); +extern mlt_position mlt_producer_position( mlt_producer this ); +extern mlt_position mlt_producer_frame( mlt_producer this ); extern int mlt_producer_set_speed( mlt_producer this, double speed ); extern double mlt_producer_get_speed( mlt_producer this ); extern double mlt_producer_get_fps( mlt_producer this ); -extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out ); -extern mlt_timecode mlt_producer_get_in( mlt_producer this ); -extern mlt_timecode mlt_producer_get_out( mlt_producer this ); -extern mlt_timecode mlt_producer_get_playtime( mlt_producer this ); -extern mlt_timecode mlt_producer_get_length( mlt_producer this ); +extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out ); +extern mlt_position mlt_producer_get_in( mlt_producer this ); +extern mlt_position mlt_producer_get_out( mlt_producer this ); +extern mlt_position mlt_producer_get_playtime( mlt_producer this ); +extern mlt_position mlt_producer_get_length( mlt_producer this ); extern void mlt_producer_prepare_next( mlt_producer this ); extern void mlt_producer_close( mlt_producer this ); diff --git a/mlt/src/framework/mlt_properties.c b/mlt/src/framework/mlt_properties.c index 679d97a..d047da0 100644 --- a/mlt/src/framework/mlt_properties.c +++ b/mlt/src/framework/mlt_properties.c @@ -285,16 +285,16 @@ int mlt_properties_set_double( mlt_properties this, char *name, double value ) /** Get a value associated to the name. */ -mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name ) +mlt_position mlt_properties_get_position( mlt_properties this, char *name ) { mlt_property value = mlt_properties_find( this, name ); - return value == NULL ? 0 : mlt_property_get_timecode( value ); + return value == NULL ? 0 : mlt_property_get_position( value ); } /** Set a value associated to the name. */ -int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value ) +int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value ) { int error = 1; @@ -303,7 +303,7 @@ int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode v // Set it if not NULL if ( property != NULL ) - error = mlt_property_set_timecode( property, value ); + error = mlt_property_set_position( property, value ); return error; } diff --git a/mlt/src/framework/mlt_properties.h b/mlt/src/framework/mlt_properties.h index 540b7ae..2cacc9f 100644 --- a/mlt/src/framework/mlt_properties.h +++ b/mlt/src/framework/mlt_properties.h @@ -48,8 +48,8 @@ extern int mlt_properties_get_int( mlt_properties this, char *name ); extern int mlt_properties_set_int( mlt_properties this, char *name, int value ); extern double mlt_properties_get_double( mlt_properties this, char *name ); extern int mlt_properties_set_double( mlt_properties this, char *name, double value ); -extern mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name ); -extern int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value ); +extern mlt_position mlt_properties_get_position( mlt_properties this, char *name ); +extern int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value ); extern int mlt_properties_set_data( mlt_properties this, char *name, void *value, int length, mlt_destructor, mlt_serialiser ); extern void *mlt_properties_get_data( mlt_properties this, char *name, int *length ); extern int mlt_properties_count( mlt_properties this ); diff --git a/mlt/src/framework/mlt_property.c b/mlt/src/framework/mlt_property.c index f471b18..0a47529 100644 --- a/mlt/src/framework/mlt_property.c +++ b/mlt/src/framework/mlt_property.c @@ -73,14 +73,14 @@ int mlt_property_set_double( mlt_property this, double value ) return 0; } -/** Set a timecode on this property. +/** Set a position on this property. */ -int mlt_property_set_timecode( mlt_property this, mlt_timecode value ) +int mlt_property_set_position( mlt_property this, mlt_position value ) { mlt_property_clear( this ); - this->types = mlt_prop_timecode; - this->prop_timecode = value; + this->types = mlt_prop_position; + this->prop_position = value; return 0; } @@ -132,8 +132,8 @@ int mlt_property_get_int( mlt_property this ) return this->prop_int; else if ( this->types & mlt_prop_double ) return ( int )this->prop_double; - else if ( this->types & mlt_prop_timecode ) - return ( int )this->prop_timecode; + else if ( this->types & mlt_prop_position ) + return ( int )this->prop_position; else if ( this->types & mlt_prop_int64 ) return ( int )this->prop_int64; else if ( this->types & mlt_prop_string ) @@ -150,8 +150,8 @@ double mlt_property_get_double( mlt_property this ) return this->prop_double; else if ( this->types & mlt_prop_int ) return ( double )this->prop_int; - else if ( this->types & mlt_prop_timecode ) - return ( double )this->prop_timecode; + else if ( this->types & mlt_prop_position ) + return ( double )this->prop_position; else if ( this->types & mlt_prop_int64 ) return ( double )this->prop_int64; else if ( this->types & mlt_prop_string ) @@ -159,21 +159,21 @@ double mlt_property_get_double( mlt_property this ) return 0; } -/** Get a timecode from this property. +/** Get a position from this property. */ -mlt_timecode mlt_property_get_timecode( mlt_property this ) +mlt_position mlt_property_get_position( mlt_property this ) { - if ( this->types & mlt_prop_timecode ) - return this->prop_timecode; + if ( this->types & mlt_prop_position ) + return this->prop_position; else if ( this->types & mlt_prop_int ) - return ( mlt_timecode )this->prop_int; + return ( mlt_position )this->prop_int; else if ( this->types & mlt_prop_double ) - return ( mlt_timecode )this->prop_double; + return ( mlt_position )this->prop_double; else if ( this->types & mlt_prop_int64 ) - return ( mlt_timecode )this->prop_int64; + return ( mlt_position )this->prop_int64; else if ( this->types & mlt_prop_string ) - return ( mlt_timecode )atof( this->prop_string ); + return ( mlt_position )atol( this->prop_string ); return 0; } @@ -188,10 +188,10 @@ int64_t mlt_property_get_int64( mlt_property this ) return ( int64_t )this->prop_int; else if ( this->types & mlt_prop_double ) return ( int64_t )this->prop_double; - else if ( this->types & mlt_prop_timecode ) - return ( int64_t )this->prop_timecode; + else if ( this->types & mlt_prop_position ) + return ( int64_t )this->prop_position; else if ( this->types & mlt_prop_string ) - return ( int64_t )atof( this->prop_string ); + return ( int64_t )atol( this->prop_string ); return 0; } @@ -215,11 +215,11 @@ char *mlt_property_get_string( mlt_property this ) this->prop_string = malloc( 32 ); sprintf( this->prop_string, "%e", this->prop_double ); } - else if ( this->types & mlt_prop_timecode ) + else if ( this->types & mlt_prop_position ) { this->types |= mlt_prop_string; this->prop_string = malloc( 32 ); - sprintf( this->prop_string, "%e", this->prop_timecode ); + sprintf( this->prop_string, "%lld", this->prop_position ); } else if ( this->types & mlt_prop_int64 ) { diff --git a/mlt/src/framework/mlt_property.h b/mlt/src/framework/mlt_property.h index 6b0def5..3f59ad2 100644 --- a/mlt/src/framework/mlt_property.h +++ b/mlt/src/framework/mlt_property.h @@ -31,7 +31,7 @@ typedef enum mlt_prop_none = 0, mlt_prop_int = 1, mlt_prop_string = 2, - mlt_prop_timecode = 4, + mlt_prop_position = 4, mlt_prop_double = 8, mlt_prop_data = 16, mlt_prop_int64 = 32 @@ -48,7 +48,7 @@ typedef struct mlt_property_s // Atomic type handling int prop_int; - mlt_timecode prop_timecode; + mlt_position prop_position; double prop_double; int64_t prop_int64; @@ -70,13 +70,13 @@ extern mlt_property mlt_property_init( ); extern void mlt_property_clear( mlt_property this ); extern int mlt_property_set_int( mlt_property this, int value ); extern int mlt_property_set_double( mlt_property this, double value ); -extern int mlt_property_set_timecode( mlt_property this, mlt_timecode value ); +extern int mlt_property_set_position( mlt_property this, mlt_position value ); extern int mlt_property_set_uint64( mlt_property this, uint64_t value ); extern int mlt_property_set_string( mlt_property this, char *value ); extern int mlt_property_set_data( mlt_property this, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser ); extern int mlt_property_get_int( mlt_property this ); extern double mlt_property_get_double( mlt_property this ); -extern mlt_timecode mlt_property_get_timecode( mlt_property this ); +extern mlt_position mlt_property_get_position( mlt_property this ); extern int64_t mlt_property_get_int64( mlt_property this ); extern char *mlt_property_get_string( mlt_property this ); extern void *mlt_property_get_data( mlt_property this, int *length ); diff --git a/mlt/src/framework/mlt_tractor.c b/mlt/src/framework/mlt_tractor.c index f4b77c4..6c02230 100644 --- a/mlt/src/framework/mlt_tractor.c +++ b/mlt/src/framework/mlt_tractor.c @@ -22,6 +22,7 @@ #include "mlt_tractor.h" #include "mlt_frame.h" +#include "mlt_multitrack.h" #include #include @@ -31,14 +32,14 @@ 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 ); /** Constructor for the tractor. @@ -50,10 +51,10 @@ 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; + producer->get_frame = producer_get_frame; } else { @@ -69,21 +70,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 +108,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; @@ -105,6 +120,25 @@ static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track int done = 0; mlt_frame temp; + // Get the properties of the parent producer + mlt_properties properties = mlt_producer_properties( parent ); + + // Try to obtain the multitrack associated to the tractor + mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", 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 ) ); + mlt_producer_set_in_and_out( parent, mlt_producer_get_in( target ), mlt_producer_get_out( target ) ); + } + else + { + fprintf( stderr, "tractor without a multitrack!!\n" ); + } + // Loop through each of the tracks we're harvesting for ( i = 0; !done; i ++ ) { @@ -133,6 +167,9 @@ static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track } } + // Prepare the next frame + mlt_producer_prepare_next( parent ); + // Indicate our found status return 0; } @@ -149,7 +186,7 @@ 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 ); + mlt_producer_close( &this->parent ); free( this ); } diff --git a/mlt/src/framework/mlt_tractor.h b/mlt/src/framework/mlt_tractor.h index 28a6071..b6576ec 100644 --- a/mlt/src/framework/mlt_tractor.h +++ b/mlt/src/framework/mlt_tractor.h @@ -25,6 +25,8 @@ extern mlt_tractor mlt_tractor_init( ); extern mlt_service mlt_tractor_service( mlt_tractor this ); +extern mlt_producer mlt_tractor_producer( mlt_tractor this ); +extern mlt_properties mlt_tractor_properties( mlt_tractor this ); extern int mlt_tractor_connect( mlt_tractor this, mlt_service service ); extern void mlt_tractor_close( mlt_tractor this ); diff --git a/mlt/src/framework/mlt_transition.c b/mlt/src/framework/mlt_transition.c index de416a8..5071550 100644 --- a/mlt/src/framework/mlt_transition.c +++ b/mlt/src/framework/mlt_transition.c @@ -46,8 +46,8 @@ int mlt_transition_init( mlt_transition this, void *child ) service->get_frame = transition_get_frame; - mlt_properties_set_timecode( properties, "in", 0 ); - mlt_properties_set_timecode( properties, "out", 0 ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", 0 ); mlt_properties_set_int( properties, "a_track", 0 ); mlt_properties_set_int( properties, "b_track", 1 ); @@ -91,11 +91,11 @@ int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_tra /** Set the in and out points. */ -void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out ) +void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out ) { mlt_properties properties = mlt_transition_properties( this ); - mlt_properties_set_timecode( properties, "in", in ); - mlt_properties_set_timecode( properties, "out", out ); + mlt_properties_set_position( properties, "in", in ); + mlt_properties_set_position( properties, "out", out ); } /** Get the index of the a track. @@ -119,19 +119,19 @@ int mlt_transition_get_b_track( mlt_transition this ) /** Get the in point. */ -mlt_timecode mlt_transition_get_in( mlt_transition this ) +mlt_position mlt_transition_get_in( mlt_transition this ) { mlt_properties properties = mlt_transition_properties( this ); - return mlt_properties_get_timecode( properties, "in" ); + return mlt_properties_get_position( properties, "in" ); } /** Get the out point. */ -mlt_timecode mlt_transition_get_out( mlt_transition this ) +mlt_position mlt_transition_get_out( mlt_transition this ) { mlt_properties properties = mlt_transition_properties( this ); - return mlt_properties_get_timecode( properties, "out" ); + return mlt_properties_get_position( properties, "out" ); } /** Process the frame. @@ -183,8 +183,8 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i int a_track = mlt_properties_get_int( properties, "a_track" ); int b_track = mlt_properties_get_int( properties, "b_track" ); - mlt_timecode in = mlt_properties_get_timecode( properties, "in" ); - mlt_timecode out = mlt_properties_get_timecode( properties, "out" ); + mlt_position in = mlt_properties_get_position( properties, "in" ); + mlt_position out = mlt_properties_get_position( properties, "out" ); // Fetch a and b frames together... if ( ( index == a_track || index == b_track ) && @@ -198,8 +198,8 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i if ( index == a_track ) { // Determine if we're in the right time zone - mlt_timecode timecode = mlt_frame_get_timecode( this->a_frame ); - if ( timecode >= in && timecode < out ) + mlt_position position = mlt_frame_get_position( this->a_frame ); + if ( position >= in && position < out ) { // Process the transition *frame = transition_process( this, this->a_frame, this->b_frame ); @@ -225,8 +225,8 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i } else { - mlt_timecode timecode = mlt_frame_get_timecode( this->b_frame ); - if ( timecode >= in && timecode < out ) + mlt_position position = mlt_frame_get_position( this->b_frame ); + if ( position >= in && position < out ) { // We're in the zone, but the 'a frame' has not been requested yet *frame = mlt_frame_init( ); diff --git a/mlt/src/framework/mlt_transition.h b/mlt/src/framework/mlt_transition.h index 7ac765c..c297bdb 100644 --- a/mlt/src/framework/mlt_transition.h +++ b/mlt/src/framework/mlt_transition.h @@ -55,11 +55,11 @@ extern int mlt_transition_init( mlt_transition this, void *child ); extern mlt_service mlt_transition_service( mlt_transition this ); extern mlt_properties mlt_transition_properties( mlt_transition this ); extern int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track ); -extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out ); +extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out ); extern int mlt_transition_get_a_track( mlt_transition this ); extern int mlt_transition_get_b_track( mlt_transition this ); -extern mlt_timecode mlt_transition_get_in( mlt_transition this ); -extern mlt_timecode mlt_transition_get_out( mlt_transition this ); +extern mlt_position mlt_transition_get_in( mlt_transition this ); +extern mlt_position mlt_transition_get_out( mlt_transition this ); extern void mlt_transition_close( mlt_transition this ); #endif diff --git a/mlt/src/framework/mlt_types.h b/mlt/src/framework/mlt_types.h index b100f18..162602f 100644 --- a/mlt/src/framework/mlt_types.h +++ b/mlt/src/framework/mlt_types.h @@ -31,7 +31,7 @@ typedef enum } mlt_whence; -typedef double mlt_timecode; +typedef int64_t mlt_position; typedef struct mlt_frame_s *mlt_frame, **mlt_frame_ptr; typedef struct mlt_properties_s *mlt_properties; typedef struct mlt_service_s *mlt_service; diff --git a/mlt/src/inigo/inigo.c b/mlt/src/inigo/inigo.c index 2dbda0e..fa76e64 100644 --- a/mlt/src/inigo/inigo.c +++ b/mlt/src/inigo/inigo.c @@ -50,43 +50,57 @@ static void transport_action( mlt_producer producer, char *value ) case '9': mlt_producer_set_speed( producer, 10 ); break; + case 'd': + if ( multitrack != NULL ) + { + int i = 0; + mlt_position last = -1; + for ( i = 0; 1; i ++ ) + { + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_start, i ); + if ( time == last ) + break; + last = time; + fprintf( stderr, "%d: %lld\n", i, time ); + } + } + break; + case 'g': if ( multitrack != NULL ) { - mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 ); + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 ); mlt_producer_seek( producer, time ); } break; case 'h': if ( multitrack != NULL ) { - mlt_producer producer = mlt_multitrack_producer( multitrack ); - int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) ); + mlt_position position = mlt_producer_position( producer ); mlt_producer_set_speed( producer, 0 ); - mlt_producer_seek_frame( producer, position - 1 >= 0 ? position - 1 : 0 ); + mlt_producer_seek( producer, position - 1 >= 0 ? position - 1 : 0 ); } break; case 'j': if ( multitrack != NULL ) { - mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 ); + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 ); mlt_producer_seek( producer, time ); } break; case 'k': if ( multitrack != NULL ) { - mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 ); + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 ); mlt_producer_seek( producer, time ); } break; case 'l': if ( multitrack != NULL ) { - mlt_producer producer = mlt_multitrack_producer( multitrack ); - int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) ); + mlt_position position = mlt_producer_position( producer ); mlt_producer_set_speed( producer, 0 ); - mlt_producer_seek_frame( producer, position + 1 ); + mlt_producer_seek( producer, position + 1 ); } break; } diff --git a/mlt/src/miracle/miracle_unit.c b/mlt/src/miracle/miracle_unit.c index 479ed71..a1043df 100644 --- a/mlt/src/miracle/miracle_unit.c +++ b/mlt/src/miracle/miracle_unit.c @@ -218,7 +218,6 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response ) mlt_properties properties = unit->properties; int generation = mlt_properties_get_int( properties, "generation" ); mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_producer producer = mlt_playlist_producer( playlist ); valerie_response_printf( response, 1024, "%d\n", generation ); @@ -230,8 +229,8 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response ) i, info.resource, info.frame_in, info.frame_out, - mlt_producer_frame_position( producer, info.playtime ), - mlt_producer_frame_position( producer, info.length ), + info.frame_count, + info.length, info.fps ); } } @@ -257,7 +256,7 @@ valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, int64_t in, { mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) ); + mlt_playlist_append_io( playlist, instance, in, out ); miracle_log( LOG_DEBUG, "loaded clip %s", clip ); miracle_unit_status_communicate( unit ); return valerie_ok; @@ -274,7 +273,7 @@ valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index { mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_playlist_insert( playlist, instance, index, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) ); + mlt_playlist_insert( playlist, instance, index, in, out ); miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index ); update_generation( unit ); miracle_unit_status_communicate( unit ); @@ -330,7 +329,7 @@ valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, int64_t i { mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) ); + mlt_playlist_append_io( playlist, instance, in, out ); miracle_log( LOG_DEBUG, "appended clip %s", clip ); update_generation( unit ); miracle_unit_status_communicate( unit ); @@ -424,13 +423,13 @@ int miracle_unit_get_status( miracle_unit unit, valerie_status status ) status->fps = mlt_producer_get_fps( producer ); status->in = info.frame_in; status->out = info.frame_out; - status->position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) ); - status->length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) ); + status->position = mlt_producer_position( clip ); + status->length = mlt_producer_get_length( clip ); strncpy( status->tail_clip, info.resource, sizeof( status->tail_clip ) ); status->tail_in = info.frame_in; status->tail_out = info.frame_out; - status->tail_position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) ); - status->tail_length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) ); + status->tail_position = mlt_producer_position( clip ); + status->tail_length = mlt_producer_get_length( clip ); status->clip_index = mlt_playlist_current_clip( playlist ); status->seek_flag = 1; } @@ -477,7 +476,7 @@ void miracle_unit_change_position( miracle_unit unit, int clip, int64_t position if ( mlt_playlist_get_clip_info( playlist, &info, clip ) == 0 ) { - int64_t frame_start = mlt_producer_frame_position( info.producer, info.start ); + int64_t frame_start = info.start; int64_t frame_offset = position; if ( frame_offset < 0 ) @@ -487,7 +486,7 @@ void miracle_unit_change_position( miracle_unit unit, int clip, int64_t position if ( frame_offset >= info.frame_out ) frame_offset = info.frame_out; - mlt_producer_seek_frame( producer, frame_start + frame_offset - info.frame_in ); + mlt_producer_seek( producer, frame_start + frame_offset - info.frame_in ); } miracle_unit_status_communicate( unit ); @@ -516,8 +515,8 @@ int miracle_unit_set_clip_in( miracle_unit unit, int index, int64_t position ) if ( error == 0 ) { - mlt_timecode in = mlt_producer_time( info.producer, position ); - error = mlt_playlist_resize_clip( playlist, index, in, info.out ); + miracle_unit_play( unit, 0 ); + error = mlt_playlist_resize_clip( playlist, index, position, info.frame_out ); update_generation( unit ); miracle_unit_change_position( unit, index, 0 ); } @@ -537,8 +536,8 @@ int miracle_unit_set_clip_out( miracle_unit unit, int index, int64_t position ) if ( error == 0 ) { - mlt_timecode out = mlt_producer_time( info.producer, position ); - error = mlt_playlist_resize_clip( playlist, index, info.in, out ); + miracle_unit_play( unit, 0 ); + error = mlt_playlist_resize_clip( playlist, index, info.frame_in, position ); update_generation( unit ); miracle_unit_status_communicate( unit ); miracle_unit_change_position( unit, index, -1 ); @@ -555,8 +554,8 @@ void miracle_unit_step( miracle_unit unit, int64_t offset ) mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); mlt_producer producer = mlt_playlist_producer( playlist ); - mlt_timecode position = mlt_producer_position( producer ); - mlt_producer_seek_frame( producer, mlt_producer_frame_position( producer, position ) + offset ); + mlt_position position = mlt_producer_frame( producer ); + mlt_producer_seek( producer, position + offset ); } /** Set the unit's clip mode regarding in and out points. diff --git a/mlt/src/modules/core/producer_ppm.c b/mlt/src/modules/core/producer_ppm.c index b508654..c929d25 100644 --- a/mlt/src/modules/core/producer_ppm.c +++ b/mlt/src/modules/core/producer_ppm.c @@ -249,7 +249,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i ( *frame )->get_audio = producer_get_audio; // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/mlt/src/modules/core/transition_composite.c b/mlt/src/modules/core/transition_composite.c index 7bcdfa9..c2ba62d 100644 --- a/mlt/src/modules/core/transition_composite.c +++ b/mlt/src/modules/core/transition_composite.c @@ -44,32 +44,42 @@ static int transition_get_image( mlt_frame this, uint8_t **image, mlt_image_form // Get the b frame from the stack mlt_frame b_frame = mlt_frame_pop_frame( this ); - // Get the properties of the b frame - mlt_properties b_props = mlt_frame_properties( b_frame ); - - // Arbitrary composite defaults - int x = 0; - int y = 0; - double mix = 1.0; - - // Override from b frame properties if provided - if ( mlt_properties_get( b_props, "x" ) != NULL ) - x = mlt_properties_get_int( b_props, "x" ); - if ( mlt_properties_get( b_props, "y" ) != NULL ) - y = mlt_properties_get_int( b_props, "y" ); - if ( mlt_properties_get( b_props, "mix" ) != NULL ) - mix = mlt_properties_get_double( b_props, "mix" ); - - // Composite the b_frame on the a_frame - mlt_frame_composite_yuv( this, b_frame, x, y, mix ); - - // Extract the a_frame image info - *width = mlt_properties_get_int( a_props, "width" ); - *height = mlt_properties_get_int( a_props, "height" ); - *image = mlt_properties_get_data( a_props, "image", NULL ); - - // Close the b_frame - mlt_frame_close( b_frame ); + if ( b_frame != NULL ) + { + // Get the properties of the b frame + mlt_properties b_props = mlt_frame_properties( b_frame ); + + // Arbitrary composite defaults + int x = 0; + int y = 0; + double mix = 1.0; + + // Override from b frame properties if provided + if ( mlt_properties_get( b_props, "x" ) != NULL ) + x = mlt_properties_get_int( b_props, "x" ); + if ( mlt_properties_get( b_props, "y" ) != NULL ) + y = mlt_properties_get_int( b_props, "y" ); + if ( mlt_properties_get( b_props, "mix" ) != NULL ) + mix = mlt_properties_get_double( b_props, "mix" ); + + // Composite the b_frame on the a_frame + mlt_frame_composite_yuv( this, b_frame, x, y, mix ); + + // Extract the a_frame image info + *width = mlt_properties_get_int( a_props, "width" ); + *height = mlt_properties_get_int( a_props, "height" ); + *image = mlt_properties_get_data( a_props, "image", NULL ); + + // Close the b_frame + mlt_frame_close( b_frame ); + } + else if ( a_props != NULL ) + { + // Extract the a_frame image info + *width = mlt_properties_get_int( a_props, "width" ); + *height = mlt_properties_get_int( a_props, "height" ); + *image = mlt_properties_get_data( a_props, "image", NULL ); + } return 0; } diff --git a/mlt/src/modules/core/transition_luma.c b/mlt/src/modules/core/transition_luma.c index a3ae3dc..71c8238 100644 --- a/mlt/src/modules/core/transition_luma.c +++ b/mlt/src/modules/core/transition_luma.c @@ -339,9 +339,9 @@ static mlt_frame transition_process( mlt_transition transition, mlt_frame a_fram } // Determine the time position of this frame in the transition duration - mlt_timecode in = mlt_transition_get_in( transition ); - mlt_timecode out = mlt_transition_get_out( transition ); - mlt_timecode time = mlt_frame_get_timecode( b_frame ); + mlt_position in = mlt_transition_get_in( transition ); + mlt_position out = mlt_transition_get_out( transition ); + mlt_position time = mlt_frame_get_position( b_frame ); double pos = ( time - in ) / ( out - in ); // Set the b frame properties diff --git a/mlt/src/modules/dv/Makefile b/mlt/src/modules/dv/Makefile index 218f85b..f3aac3c 100644 --- a/mlt/src/modules/dv/Makefile +++ b/mlt/src/modules/dv/Makefile @@ -2,7 +2,8 @@ TARGET = ../libmltdv.so OBJS = factory.o \ - producer_libdv.o + producer_libdv.o \ + consumer_libdv.o CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread diff --git a/mlt/src/modules/dv/configure b/mlt/src/modules/dv/configure index 876897c..9453267 100755 --- a/mlt/src/modules/dv/configure +++ b/mlt/src/modules/dv/configure @@ -7,5 +7,9 @@ cat << EOF >> ../producers.dat libdv libmltdv.so EOF +cat << EOF >> ../consumers.dat +libdv libmltdv.so +EOF + fi diff --git a/mlt/src/modules/dv/consumer_libdv.c b/mlt/src/modules/dv/consumer_libdv.c new file mode 100644 index 0000000..07bd6e6 --- /dev/null +++ b/mlt/src/modules/dv/consumer_libdv.c @@ -0,0 +1,329 @@ +/* + * producer_libdv.c -- a DV encoder based on libdv + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// Local header files +#include "consumer_libdv.h" + +// mlt Header files +#include + +// System header files +#include +#include +#include +#include + +// libdv header files +#include + +// Forward references. +static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ); +static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ); +static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame ); +static void *consumer_thread( void *arg ); +static void consumer_close( mlt_consumer this ); + +/** Initialise the dv consumer. +*/ + +mlt_consumer consumer_libdv_init( char *arg ) +{ + // Allocate the consumer + mlt_consumer this = calloc( 1, sizeof( struct mlt_consumer_s ) ); + + // If memory allocated and initialises without error + if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 ) + { + // Get properties from the consumer + mlt_properties properties = mlt_consumer_properties( this ); + + // Allocate a thread + pthread_t *thread = calloc( 1, sizeof( pthread_t ) ); + + // Assign close callback + this->close = consumer_close; + + // Assign all properties + if ( arg == NULL || !strcmp( arg, "PAL" ) ) + mlt_properties_set_double( properties, "fps", 25 ); + else + mlt_properties_set_double( properties, "fps", 29.97 ); + + mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL ); + mlt_properties_set_data( properties, "video", consumer_encode_video, 0, NULL, NULL ); + mlt_properties_set_data( properties, "audio", consumer_encode_audio, 0, NULL, NULL ); + mlt_properties_set_data( properties, "output", consumer_output, 0, NULL, NULL ); + + // Create the thread (this should not happen immediately) + mlt_properties_set_int( properties, "running", 1 ); + pthread_create( thread, NULL, consumer_thread, this ); + } + else + { + // Clean up in case of init failure + free( this ); + this = NULL; + } + + // Return this + return this; +} + +/** Get or create a new libdv encoder. +*/ + +static dv_encoder_t *libdv_get_encoder( mlt_consumer this, mlt_frame frame ) +{ + // Get the properties of the consumer + mlt_properties this_properties = mlt_consumer_properties( this ); + + // Obtain the dv_encoder + dv_encoder_t *encoder = mlt_properties_get_data( this_properties, "dv_encoder", NULL ); + + // Construct one if we don't have one + if ( encoder == NULL ) + { + // Get the fps of the consumer (for now - should be from frame) + double fps = mlt_properties_get_double( this_properties, "fps" ); + + // Create the encoder + encoder = dv_encoder_new( fps != 25, 0, 0 ); + + // Encoder settings + encoder->isPAL = fps = 25; + encoder->is16x9 = 0; + encoder->vlc_encode_passes = 1; + encoder->static_qno = 0; + encoder->force_dct = DV_DCT_AUTO; + + // Store the encoder on the properties + mlt_properties_set_data( this_properties, "dv_encoder", encoder, 0, ( mlt_destructor )dv_encoder_free, NULL ); + + // Convenience for image dimensions + mlt_properties_set_int( this_properties, "width", 720 ); + mlt_properties_set_int( this_properties, "height", fps == 25 ? 576 : 480 ); + } + + // Return the encoder + return encoder; +} + + +/** The libdv encode video method. +*/ + +static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ) +{ + // Obtain the dv_encoder + dv_encoder_t *encoder = libdv_get_encoder( this, frame ); + + // Get the properties of the consumer + mlt_properties this_properties = mlt_consumer_properties( this ); + + // This will hold the size of the dv frame + int size = 0; + + // If we get an encoder, then encode the image + if ( encoder != NULL ) + { + // Specify desired image properties + mlt_image_format fmt = mlt_image_yuv422; + int width = mlt_properties_get_int( this_properties, "width" ); + int height = mlt_properties_get_int( this_properties, "height" ); + uint8_t *image = NULL; + + // Get the image + mlt_frame_get_image( frame, &image, &fmt, &width, &height, 0 ); + + // Check that we get what we expected + if ( fmt != mlt_image_yuv422 || + width != mlt_properties_get_int( this_properties, "width" ) || + height != mlt_properties_get_int( this_properties, "height" ) || + image == NULL ) + { + // We should try to recover here + fprintf( stderr, "We have a problem houston...\n" ); + } + else + { + // Calculate the size of the dv frame + size = height == 576 ? frame_size_625_50 : frame_size_525_60; + } + + // Process the frame + if ( size != 0 ) + { + // Encode the image + dv_encode_full_frame( encoder, &image, e_dv_color_yuv, dv_frame ); + } + } + + return size; +} + +/** The libdv encode audio method. +*/ + +static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ) +{ + // Get the properties of the consumer + mlt_properties this_properties = mlt_consumer_properties( this ); + + // Obtain the dv_encoder + dv_encoder_t *encoder = libdv_get_encoder( this, frame ); + + // Only continue if we have an encoder + if ( encoder != NULL ) + { + // Get the frame count + int count = mlt_properties_get_int( this_properties, "count" ); + + // Default audio args + mlt_audio_format fmt = mlt_audio_pcm; + int channels = 2; + int frequency = 48000; + int samples = mlt_sample_calculator( mlt_properties_get_double( this_properties, "fps" ), frequency, count ); + int16_t *pcm = NULL; + + // Get the frame number + time_t start = time( NULL ); + int height = mlt_properties_get_int( this_properties, "height" ); + int is_pal = height == 576; + int is_wide = 0; + + // Temporary - audio buffer allocation + int16_t *audio_buffers[ 4 ]; + int i = 0; + int j = 0; + for ( i = 0 ; i < 4; i ++ ) + audio_buffers[ i ] = malloc( 2 * DV_AUDIO_MAX_SAMPLES ); + + // Get the audio + mlt_frame_get_audio( frame, &pcm, &fmt, &frequency, &channels, &samples ); + + // Inform the encoder of the number of audio samples + encoder->samples_this_frame = samples; + + // Fill the audio buffers correctly + for ( i = 0; i < samples; i ++ ) + for ( j = 0; j < channels; j++ ) + audio_buffers[ j ][ i ] = *pcm ++; + + // Encode audio on frame + dv_encode_full_audio( encoder, audio_buffers, channels, frequency, dv_frame ); + + // Specify meta data on the frame + dv_encode_metadata( dv_frame, is_pal, is_wide, &start, count ); + dv_encode_timecode( dv_frame, is_pal, count ); + + // Update properties + mlt_properties_set_int( this_properties, "count", ++ count ); + + // Temporary - free audio buffers + for ( i = 0 ; i < 4; i ++ ) + free( audio_buffers[ i ] ); + } +} + +/** The libdv output method. +*/ + +static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame ) +{ + fwrite( dv_frame, size, 1, stdout ); + fflush( stdout ); +} + +/** The main thread - the argument is simply the consumer. +*/ + +static void *consumer_thread( void *arg ) +{ + // Map the argument to the object + mlt_consumer this = arg; + + // Get the properties + mlt_properties properties = mlt_consumer_properties( this ); + + // Get the handling methods + int ( *video )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "video", NULL ); + int ( *audio )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "audio", NULL ); + int ( *output )( mlt_consumer, uint8_t *, int, mlt_frame ) = mlt_properties_get_data( properties, "output", NULL ); + + // Allocate a single PAL frame for encoding + uint8_t *dv_frame = malloc( frame_size_625_50 ); + + // Get the service associated to the consumer + mlt_service service = mlt_consumer_service( this ); + + // Define a frame pointer + mlt_frame frame; + + // Loop while running + while( mlt_properties_get_int( properties, "running" ) ) + { + // Get the frame + if ( mlt_service_get_frame( service, &frame, 0 ) == 0 ) + { + // Encode the image + int size = video( this, dv_frame, frame ); + + // Encode the audio + if ( size > 0 ) + audio( this, dv_frame, frame ); + + // Output the frame + output( this, dv_frame, size, frame ); + + // Close the frame + mlt_frame_close( frame ); + } + } + + // Tidy up + free( dv_frame ); + + return NULL; +} + +/** Close the consumer. +*/ + +static void consumer_close( mlt_consumer this ) +{ + // Get the properties + mlt_properties properties = mlt_consumer_properties( this ); + + // Get the thread + pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL ); + + // Stop the thread + mlt_properties_set_int( properties, "running", 0 ); + + // Wait for termination + pthread_join( *thread, NULL ); + + // Close the parent + mlt_consumer_close( this ); + + // Free the memory + free( this ); +} + diff --git a/mlt/src/modules/dv/consumer_libdv.h b/mlt/src/modules/dv/consumer_libdv.h new file mode 100644 index 0000000..de7311e --- /dev/null +++ b/mlt/src/modules/dv/consumer_libdv.h @@ -0,0 +1,28 @@ +/* + * producer_libdv.h -- a DV encoder based on libdv + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CONSUMER_LIBDV_H_ +#define _CONSUMER_LIBDV_H_ + +#include + +extern mlt_consumer consumer_libdv_init( char *filename ); + +#endif diff --git a/mlt/src/modules/dv/factory.c b/mlt/src/modules/dv/factory.c index e27510a..8d25f70 100644 --- a/mlt/src/modules/dv/factory.c +++ b/mlt/src/modules/dv/factory.c @@ -21,6 +21,7 @@ #include #include "producer_libdv.h" +#include "consumer_libdv.h" void *mlt_create_producer( char *id, void *arg ) { @@ -41,6 +42,8 @@ void *mlt_create_transition( char *id, void *arg ) void *mlt_create_consumer( char *id, void *arg ) { + if ( !strcmp( id, "libdv" ) ) + return consumer_libdv_init( arg ); return NULL; } diff --git a/mlt/src/modules/dv/producer_libdv.c b/mlt/src/modules/dv/producer_libdv.c index 8c139df..b82a0e6 100644 --- a/mlt/src/modules/dv/producer_libdv.c +++ b/mlt/src/modules/dv/producer_libdv.c @@ -130,11 +130,10 @@ static int producer_collect_info( producer_libdv this ) // Calculate default in/out points double fps = this->is_pal ? 25 : 30000.0 / 1001.0; - mlt_timecode length = ( mlt_timecode )( this->frames_in_file ) / fps; mlt_properties_set_double( properties, "fps", fps ); - mlt_properties_set_timecode( properties, "length", length ); - mlt_properties_set_timecode( properties, "in", 0.0 ); - mlt_properties_set_timecode( properties, "out", ( mlt_timecode )( this->frames_in_file - 1 ) / fps ); + mlt_properties_set_position( properties, "length", this->frames_in_file ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", this->frames_in_file - 1 ); // Parse the header for meta info dv_parse_header( this->dv_decoder, dv_data ); @@ -307,7 +306,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i } // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c b/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c index 652354b..0d678af 100644 --- a/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c +++ b/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c @@ -47,7 +47,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) ) { // Get the position - double position = mlt_properties_get_double( producer_properties, "dub_position" ); + mlt_position position = mlt_properties_get_position( producer_properties, "dub_position" ); // We need a frame from the producer mlt_frame producer_frame; @@ -56,7 +56,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format mlt_properties_set_double( producer_properties, "fps", mlt_properties_get_double( frame_properties, "fps" ) ); // Seek to the position - mlt_producer_seek_frame( producer, ( int64_t )position ); + mlt_producer_seek( producer, position ); // Get the next frame producer->get_frame( producer, &producer_frame, 0 ); @@ -70,7 +70,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format mlt_properties_set_data( frame_properties, "ffmpeg_dub_frame", producer_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); // Incrment the position - mlt_properties_set_double( producer_properties, "dub_position", position + 1 ); + mlt_properties_set_position( producer_properties, "dub_position", position + 1 ); } } @@ -135,7 +135,7 @@ mlt_filter filter_ffmpeg_dub_init( char *file ) mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL ); // Initialise the audio frame position - mlt_properties_set_double( properties, "dub_position", 0 ); + mlt_properties_set_position( properties, "dub_position", 0 ); return this; } diff --git a/mlt/src/modules/ffmpeg/producer_ffmpeg.c b/mlt/src/modules/ffmpeg/producer_ffmpeg.c index 9233bb3..f383aff 100644 --- a/mlt/src/modules/ffmpeg/producer_ffmpeg.c +++ b/mlt/src/modules/ffmpeg/producer_ffmpeg.c @@ -240,7 +240,7 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma return 0; } -FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_timecode position ) +FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_position position ) { if ( this->video == NULL ) { @@ -277,7 +277,7 @@ FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_timecode position ) return this->video; } -FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_timecode position ) +FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_position position ) { // Get the producer mlt_producer producer = &this->parent; @@ -530,12 +530,12 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i if ( this->end_of_video && this->end_of_audio ) { mlt_properties_set_int( properties, "end_of_clip", 1 ); - mlt_properties_set_timecode( producer_properties, "length", mlt_producer_position( &this->parent ) ); + mlt_properties_set_position( producer_properties, "length", mlt_producer_position( &this->parent ) ); mlt_producer_set_in_and_out( &this->parent, mlt_producer_get_in( &this->parent ), mlt_producer_position( &this->parent ) ); } // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/mlt/src/modules/gtk2/producer_pango.c b/mlt/src/modules/gtk2/producer_pango.c index 752ed4a..2a8d99f 100644 --- a/mlt/src/modules/gtk2/producer_pango.c +++ b/mlt/src/modules/gtk2/producer_pango.c @@ -340,7 +340,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i } // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/mlt/src/modules/gtk2/producer_pixbuf.c b/mlt/src/modules/gtk2/producer_pixbuf.c index 84ed6e6..04a9e64 100644 --- a/mlt/src/modules/gtk2/producer_pixbuf.c +++ b/mlt/src/modules/gtk2/producer_pixbuf.c @@ -90,7 +90,7 @@ mlt_producer producer_pixbuf_init( char *filename ) gap ++; } } - mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_position( properties, "out", this->count * 25 ); } else if ( strstr( filename, "/.all." ) != NULL ) { @@ -117,7 +117,7 @@ mlt_producer producer_pixbuf_init( char *filename ) free( de[ i ] ); } - mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_position( properties, "out", this->count * 25 ); free( de ); free( dir_name ); } @@ -125,7 +125,7 @@ mlt_producer producer_pixbuf_init( char *filename ) { this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); this->filenames[ this->count ++ ] = strdup( filename ); - mlt_properties_set_timecode( properties, "out", 1 ); + mlt_properties_set_position( properties, "out", 25 ); } // Initialise gobject types @@ -207,7 +207,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count; // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // optimization for subsequent iterations on single picture if ( this->image != NULL && image_idx == this->image_idx ) diff --git a/mlt/src/modules/inigo/producer_inigo.c b/mlt/src/modules/inigo/producer_inigo.c index 581db3d..62e02b2 100644 --- a/mlt/src/modules/inigo/producer_inigo.c +++ b/mlt/src/modules/inigo/producer_inigo.c @@ -241,10 +241,15 @@ mlt_producer producer_inigo_init( char **argv ) mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), track ); } - mlt_properties props = mlt_multitrack_properties( multitrack ); + mlt_tractor tractor = mlt_field_tractor( field ); + mlt_producer prod = mlt_tractor_producer( tractor ); + mlt_properties props = mlt_tractor_properties( tractor ); + mlt_properties_set_data( props, "multitrack", multitrack, 0, NULL, NULL ); mlt_properties_set_data( props, "field", field, 0, NULL, NULL ); mlt_properties_set_data( props, "group", group, 0, NULL, NULL ); + mlt_producer_set_in_and_out( prod, 0, mlt_producer_get_out( mlt_multitrack_producer( multitrack ) ) ); + mlt_properties_set_double( props, "fps", mlt_producer_get_fps( mlt_multitrack_producer( multitrack ) ) ); - return mlt_multitrack_producer( multitrack ); + return mlt_tractor_producer( tractor ); } diff --git a/mlt/src/modules/sdl/consumer_sdl.c b/mlt/src/modules/sdl/consumer_sdl.c index 803e96e..e56d56c 100644 --- a/mlt/src/modules/sdl/consumer_sdl.c +++ b/mlt/src/modules/sdl/consumer_sdl.c @@ -529,8 +529,7 @@ static void consumer_close( mlt_consumer parent ) pthread_mutex_destroy( &this->audio_mutex ); pthread_cond_destroy( &this->audio_cond ); - // Now clean up the rest (the close = NULL is a bit nasty but needed for now) - parent->close = NULL; + // Now clean up the rest mlt_consumer_close( parent ); // Finally clean up this diff --git a/src/framework/mlt_consumer.c b/src/framework/mlt_consumer.c index f263a20..5ff7f5f 100644 --- a/src/framework/mlt_consumer.c +++ b/src/framework/mlt_consumer.c @@ -63,8 +63,15 @@ int mlt_consumer_connect( mlt_consumer this, mlt_service producer ) void mlt_consumer_close( mlt_consumer this ) { - if ( this->close != NULL ) - this->close( this ); + // Get the childs close function + void ( *consumer_close )( ) = this->close; + + // Make sure it only gets called once + this->close = NULL; + + // Call the childs close if available + if ( consumer_close != NULL ) + consumer_close( this ); else mlt_service_close( &this->parent ); } diff --git a/src/framework/mlt_factory.c b/src/framework/mlt_factory.c index 9795770..9223178 100644 --- a/src/framework/mlt_factory.c +++ b/src/framework/mlt_factory.c @@ -19,9 +19,8 @@ */ #include "config.h" -#include "mlt_factory.h" +#include "mlt.h" #include "mlt_repository.h" -#include "mlt_properties.h" #include #include @@ -41,22 +40,26 @@ static mlt_repository consumers = NULL; int mlt_factory_init( char *prefix ) { - // If no directory is specified, default to install directory - if ( prefix == NULL ) - prefix = PREFIX_DATA; - - // Store the prefix for later retrieval - mlt_prefix = strdup( prefix ); - - // Create the object list. - object_list = calloc( sizeof( struct mlt_properties_s ), 1 ); - mlt_properties_init( object_list, NULL ); - - // Create a repository for each service type - producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" ); - filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" ); - transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" ); - consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" ); + // Only initialise once + if ( mlt_prefix == NULL ) + { + // If no directory is specified, default to install directory + if ( prefix == NULL ) + prefix = PREFIX_DATA; + + // Store the prefix for later retrieval + mlt_prefix = strdup( prefix ); + + // Create the object list. + object_list = calloc( sizeof( struct mlt_properties_s ), 1 ); + mlt_properties_init( object_list, NULL ); + + // Create a repository for each service type + producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" ); + filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" ); + transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" ); + consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" ); + } return 0; } @@ -74,7 +77,14 @@ const char *mlt_factory_prefix( ) mlt_producer mlt_factory_producer( char *service, void *input ) { - return ( mlt_producer )mlt_repository_fetch( producers, service, input ); + mlt_producer obj = mlt_repository_fetch( producers, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_producer_properties( obj ); + mlt_properties_set( properties, "mlt_type", "producer" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Fetch a filter from the repository. @@ -82,7 +92,14 @@ mlt_producer mlt_factory_producer( char *service, void *input ) mlt_filter mlt_factory_filter( char *service, void *input ) { - return ( mlt_filter )mlt_repository_fetch( filters, service, input ); + mlt_filter obj = mlt_repository_fetch( filters, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_filter_properties( obj ); + mlt_properties_set( properties, "mlt_type", "filter" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Fetch a transition from the repository. @@ -90,7 +107,14 @@ mlt_filter mlt_factory_filter( char *service, void *input ) mlt_transition mlt_factory_transition( char *service, void *input ) { - return ( mlt_transition )mlt_repository_fetch( transitions, service, input ); + mlt_transition obj = mlt_repository_fetch( transitions, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_transition_properties( obj ); + mlt_properties_set( properties, "mlt_type", "transition" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Fetch a consumer from the repository @@ -98,7 +122,14 @@ mlt_transition mlt_factory_transition( char *service, void *input ) mlt_consumer mlt_factory_consumer( char *service, void *input ) { - return ( mlt_consumer )mlt_repository_fetch( consumers, service, input ); + mlt_consumer obj = mlt_repository_fetch( consumers, service, input ); + if ( obj != NULL ) + { + mlt_properties properties = mlt_consumer_properties( obj ); + mlt_properties_set( properties, "mlt_type", "consumer" ); + mlt_properties_set( properties, "mlt_service", service ); + } + return obj; } /** Close the factory. @@ -106,12 +137,16 @@ mlt_consumer mlt_factory_consumer( char *service, void *input ) void mlt_factory_close( ) { - mlt_repository_close( producers ); - mlt_repository_close( filters ); - mlt_repository_close( transitions ); - mlt_repository_close( consumers ); - mlt_properties_close( object_list ); - free( mlt_prefix ); - free( object_list ); + if ( mlt_prefix != NULL ) + { + mlt_repository_close( producers ); + mlt_repository_close( filters ); + mlt_repository_close( transitions ); + mlt_repository_close( consumers ); + mlt_properties_close( object_list ); + free( mlt_prefix ); + free( object_list ); + mlt_prefix = NULL; + } } diff --git a/src/framework/mlt_field.c b/src/framework/mlt_field.c index a54d97e..8a7f51f 100644 --- a/src/framework/mlt_field.c +++ b/src/framework/mlt_field.c @@ -89,6 +89,14 @@ mlt_multitrack mlt_field_multitrack( mlt_field this ) return this->multitrack; } +/** Get the tractor. +*/ + +mlt_tractor mlt_field_tractor( mlt_field this ) +{ + return this->tractor; +} + /** Get the properties associated to this field. */ diff --git a/src/framework/mlt_field.h b/src/framework/mlt_field.h index 6fef296..d84d0cc 100644 --- a/src/framework/mlt_field.h +++ b/src/framework/mlt_field.h @@ -25,6 +25,7 @@ extern mlt_field mlt_field_init( ); extern mlt_service mlt_field_service( mlt_field this ); +extern mlt_tractor mlt_field_tractor( mlt_field this ); extern mlt_multitrack mlt_field_multitrack( mlt_field this ); extern mlt_properties mlt_field_properties( mlt_field this ); extern int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track ); diff --git a/src/framework/mlt_filter.c b/src/framework/mlt_filter.c index 9c0a295..6e39e79 100644 --- a/src/framework/mlt_filter.c +++ b/src/framework/mlt_filter.c @@ -45,8 +45,8 @@ int mlt_filter_init( mlt_filter this, void *child ) service->get_frame = filter_get_frame; // Default in, out, track properties - mlt_properties_set_timecode( properties, "in", 0 ); - mlt_properties_set_timecode( properties, "out", 0 ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", 0 ); mlt_properties_set_int( properties, "track", 0 ); return 0; @@ -80,8 +80,8 @@ int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ) { mlt_properties properties = mlt_service_properties( &this->parent ); this->producer = producer; - mlt_properties_set_timecode( properties, "in", 0 ); - mlt_properties_set_timecode( properties, "out", 0 ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", 0 ); mlt_properties_set_int( properties, "track", index ); } @@ -91,11 +91,11 @@ int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ) /** Tune the in/out points. */ -void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out ) +void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out ) { mlt_properties properties = mlt_service_properties( &this->parent ); - mlt_properties_set_timecode( properties, "in", in ); - mlt_properties_set_timecode( properties, "out", out ); + mlt_properties_set_position( properties, "in", in ); + mlt_properties_set_position( properties, "out", out ); } /** Return the track that this filter is operating on. @@ -110,19 +110,19 @@ int mlt_filter_get_track( mlt_filter this ) /** Get the in point. */ -mlt_timecode mlt_filter_get_in( mlt_filter this ) +mlt_position mlt_filter_get_in( mlt_filter this ) { mlt_properties properties = mlt_service_properties( &this->parent ); - return mlt_properties_get_timecode( properties, "in" ); + return mlt_properties_get_position( properties, "in" ); } /** Get the out point. */ -mlt_timecode mlt_filter_get_out( mlt_filter this ) +mlt_position mlt_filter_get_out( mlt_filter this ) { mlt_properties properties = mlt_service_properties( &this->parent ); - return mlt_properties_get_timecode( properties, "out" ); + return mlt_properties_get_position( properties, "out" ); } /** Process the frame. @@ -156,8 +156,8 @@ static int filter_get_frame( mlt_service service, mlt_frame_ptr frame, int index { if ( !mlt_frame_is_test_card( *frame ) ) { - mlt_timecode timecode = mlt_frame_get_timecode( *frame ); - if ( timecode >= in && ( out == 0 || timecode < out ) ) + mlt_position position = mlt_frame_get_position( *frame ); + if ( position >= in && ( out == 0 || position < out ) ) *frame = filter_process( this, *frame ); } return 0; diff --git a/src/framework/mlt_filter.h b/src/framework/mlt_filter.h index e3f0f74..edaf6f6 100644 --- a/src/framework/mlt_filter.h +++ b/src/framework/mlt_filter.h @@ -51,10 +51,10 @@ extern int mlt_filter_init( mlt_filter this, void *child ); extern mlt_service mlt_filter_service( mlt_filter this ); extern mlt_properties mlt_filter_properties( mlt_filter this ); extern int mlt_filter_connect( mlt_filter this, mlt_service producer, int index ); -extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out ); +extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out ); extern int mlt_filter_get_track( mlt_filter this ); -extern mlt_timecode mlt_filter_get_in( mlt_filter this ); -extern mlt_timecode mlt_filter_get_out( mlt_filter this ); +extern mlt_position mlt_filter_get_in( mlt_filter this ); +extern mlt_position mlt_filter_get_out( mlt_filter this ); extern void mlt_filter_close( mlt_filter ); #endif diff --git a/src/framework/mlt_frame.c b/src/framework/mlt_frame.c index a51fb7e..cb26ee9 100644 --- a/src/framework/mlt_frame.c +++ b/src/framework/mlt_frame.c @@ -53,7 +53,7 @@ mlt_frame mlt_frame_init( ) mlt_properties_init( properties, this ); // Set default properties on the frame - mlt_properties_set_timecode( properties, "timecode", 0.0 ); + mlt_properties_set_position( properties, "position", 0.0 ); mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL ); mlt_properties_set_int( properties, "width", 720 ); mlt_properties_set_int( properties, "height", 576 ); @@ -98,22 +98,22 @@ int mlt_frame_set_aspect_ratio( mlt_frame this, double value ) return mlt_properties_set_double( properties, "aspect_ratio", value ); } -/** Get the timecode of this frame. +/** Get the position of this frame. */ -mlt_timecode mlt_frame_get_timecode( mlt_frame this ) +mlt_position mlt_frame_get_position( mlt_frame this ) { mlt_properties properties = mlt_frame_properties( this ); - return mlt_properties_get_timecode( properties, "timecode" ); + return mlt_properties_get_position( properties, "position" ); } -/** Set the timecode of this frame. +/** Set the position of this frame. */ -int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value ) +int mlt_frame_set_position( mlt_frame this, mlt_position value ) { mlt_properties properties = mlt_frame_properties( this ); - return mlt_properties_set_timecode( properties, "timecode", value ); + return mlt_properties_set_position( properties, "position", value ); } /** Stack a get_image callback. @@ -709,7 +709,7 @@ int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight, int16_t * int i, j; mlt_frame_get_audio( this, &p_dest, format, &frequency_dest, &channels_dest, &samples_dest ); - //fprintf( stderr, "frame dest samples %d channels %d timecode %f\n", samples_dest, channels_dest, mlt_properties_get_timecode( mlt_frame_properties( this ), "timecode" ) ); + //fprintf( stderr, "frame dest samples %d channels %d position %f\n", samples_dest, channels_dest, mlt_properties_get_position( mlt_frame_properties( this ), "position" ) ); mlt_frame_get_audio( that, &p_src, format, &frequency_src, &channels_src, &samples_src ); //fprintf( stderr, "frame src samples %d channels %d\n", samples_src, channels_src ); if ( channels_src > 6 ) diff --git a/src/framework/mlt_frame.h b/src/framework/mlt_frame.h index 175df0a..58476d5 100644 --- a/src/framework/mlt_frame.h +++ b/src/framework/mlt_frame.h @@ -70,8 +70,8 @@ extern mlt_properties mlt_frame_properties( mlt_frame this ); extern int mlt_frame_is_test_card( mlt_frame this ); extern double mlt_frame_get_aspect_ratio( mlt_frame this ); extern int mlt_frame_set_aspect_ratio( mlt_frame this, double value ); -extern mlt_timecode mlt_frame_get_timecode( mlt_frame this ); -extern int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value ); +extern mlt_position mlt_frame_get_position( mlt_frame this ); +extern int mlt_frame_set_position( mlt_frame this, mlt_position value ); extern int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ); extern uint8_t *mlt_frame_get_alpha_mask( mlt_frame this ); diff --git a/src/framework/mlt_multitrack.c b/src/framework/mlt_multitrack.c index 893cef5..47bc271 100644 --- a/src/framework/mlt_multitrack.c +++ b/src/framework/mlt_multitrack.c @@ -96,7 +96,7 @@ mlt_properties mlt_multitrack_properties( mlt_multitrack this ) return mlt_service_properties( mlt_multitrack_service( this ) ); } -/** Initialise timecode related information. +/** Initialise position related information. */ void mlt_multitrack_refresh( mlt_multitrack this ) @@ -107,7 +107,7 @@ void mlt_multitrack_refresh( mlt_multitrack this ) mlt_properties properties = mlt_multitrack_properties( this ); // We need to ensure that the multitrack reports the longest track as its length - mlt_timecode length = 0; + mlt_position length = 0; // We need to ensure that fps are the same on all services double fps = 0; @@ -146,8 +146,8 @@ void mlt_multitrack_refresh( mlt_multitrack this ) } // Update multitrack properties now - we'll not destroy the in point here - mlt_properties_set_timecode( properties, "length", length ); - mlt_properties_set_timecode( properties, "out", length ); + mlt_properties_set_position( properties, "length", length ); + mlt_properties_set_position( properties, "out", length ); mlt_properties_set_double( properties, "fps", fps ); } @@ -208,10 +208,10 @@ int mlt_multitrack_connect( mlt_multitrack this, mlt_producer producer, int trac 0.0, 1.0, b0.0, 0.1, b1.1, 1.1, 0.1, 0.2, [out of playlist2], [out of playlist1] */ -mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ) +mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ) { int first = 1; - mlt_timecode position = 0; + mlt_position position = 0; int i = 0; // Loop through each of the tracks @@ -232,7 +232,7 @@ mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int in // We only consider playlists if ( playlist != NULL ) { - // Locate the smallest timecode + // Locate the smallest position if ( first ) { // First position found @@ -244,13 +244,17 @@ mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int in else { // Obtain the clip position in this playlist - mlt_timecode position2 = mlt_playlist_clip( playlist, whence, index ); + //mlt_position position2 = mlt_playlist_clip( playlist, whence, index ); // If this position is prior to the first, then use it - if ( position2 < position ) - position = position2; + //if ( position2 < position ) + //position = position2; } } + else + { + fprintf( stderr, "track %d isn't a playlist\n", index ); + } } } @@ -293,11 +297,11 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int ind // Get the producer for this track mlt_producer producer = this->list[ index ]; - // Obtain the current timecode + // Obtain the current position uint64_t position = mlt_producer_frame( parent ); // Make sure we're at the same point - mlt_producer_seek_frame( producer, position ); + mlt_producer_seek( producer, position ); // Get the frame from the producer mlt_service_get_frame( mlt_producer_service( producer ), frame, 0 ); @@ -313,8 +317,8 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int ind // Generate a test frame *frame = mlt_frame_init( ); - // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( parent ) ); + // Update position on the frame we're creating + mlt_frame_set_position( *frame, mlt_producer_position( parent ) ); // Move on to the next frame if ( index >= this->count ) diff --git a/src/framework/mlt_multitrack.h b/src/framework/mlt_multitrack.h index 83f34dd..3f6d8d9 100644 --- a/src/framework/mlt_multitrack.h +++ b/src/framework/mlt_multitrack.h @@ -31,7 +31,7 @@ extern mlt_producer mlt_multitrack_producer( mlt_multitrack this ); extern mlt_service mlt_multitrack_service( mlt_multitrack this ); extern mlt_properties mlt_multitrack_properties( mlt_multitrack this ); extern int mlt_multitrack_connect( mlt_multitrack this, mlt_producer producer, int track ); -extern mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ); +extern mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index ); extern void mlt_multitrack_close( mlt_multitrack this ); #endif diff --git a/src/framework/mlt_playlist.c b/src/framework/mlt_playlist.c index 519585c..921bbd5 100644 --- a/src/framework/mlt_playlist.c +++ b/src/framework/mlt_playlist.c @@ -33,10 +33,9 @@ typedef struct { mlt_producer producer; - int64_t frame_in; - int64_t frame_out; - int64_t frame_count; - mlt_timecode playtime; + mlt_position frame_in; + mlt_position frame_out; + mlt_position frame_count; } playlist_entry; @@ -111,13 +110,16 @@ mlt_properties mlt_playlist_properties( mlt_playlist this ) return mlt_producer_properties( &this->parent ); } +/** Refresh the playlist after a clip has been changed. +*/ + static int mlt_playlist_virtual_refresh( mlt_playlist this ) { int i = 0; // Get the fps of the first producer double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "first_fps" ); - mlt_timecode playtime = 0; + mlt_position frame_count = 0; for ( i = 0; i < this->count; i ++ ) { @@ -139,15 +141,15 @@ static int mlt_playlist_virtual_refresh( mlt_playlist this ) mlt_properties_set_double( mlt_producer_properties( producer ), "fps", fps ); } - // Update the playtime for this clip - playtime += this->list[ i ]->playtime; + // Update the frame_count for this clip + frame_count += this->list[ i ]->frame_count; } // Refresh all properties mlt_properties_set_double( mlt_playlist_properties( this ), "first_fps", fps ); mlt_properties_set_double( mlt_playlist_properties( this ), "fps", fps == 0 ? 25 : fps ); - mlt_properties_set_timecode( mlt_playlist_properties( this ), "length", playtime ); - mlt_properties_set_timecode( mlt_playlist_properties( this ), "out", playtime ); + mlt_properties_set_position( mlt_playlist_properties( this ), "length", frame_count ); + mlt_properties_set_position( mlt_playlist_properties( this ), "out", frame_count ); return 0; } @@ -155,11 +157,8 @@ static int mlt_playlist_virtual_refresh( mlt_playlist this ) /** Append to the virtual playlist. */ -static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, int64_t in, int64_t out ) +static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out ) { - double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "fps" ); - double playtime = ( double )( out - in + 1 ) / fps; - // Check that we have room if ( this->count >= this->size ) { @@ -175,7 +174,6 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer this->list[ this->count ]->frame_in = in; this->list[ this->count ]->frame_out = out; this->list[ this->count ]->frame_count = out - in + 1; - this->list[ this->count ]->playtime = playtime; mlt_producer_set_speed( producer, 0 ); @@ -193,21 +191,27 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) mlt_producer producer = NULL; // Map playlist position to real producer in virtual playlist - mlt_timecode pos = mlt_producer_position( &this->parent ); - int64_t position = mlt_producer_frame_position( &this->parent, pos ); + mlt_position position = mlt_producer_frame( &this->parent ); + + // Total number of frames int64_t total = 0; + // Get the properties mlt_properties properties = mlt_playlist_properties( this ); + + // Get the eof handling char *eof = mlt_properties_get( properties, "eof" ); - // Loop through the virtual playlist + // Index for the main loop int i = 0; + // Loop for each producer until found for ( i = 0; i < this->count; i ++ ) { // Increment the total total += this->list[ i ]->frame_count; + // Check if the position indicates that we have found the clip if ( position < this->list[ i ]->frame_count ) { // Found it, now break @@ -225,47 +229,43 @@ static mlt_producer mlt_playlist_virtual_seek( mlt_playlist this ) if ( producer != NULL ) { position += this->list[ i ]->frame_in; - position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - mlt_producer_seek_frame( producer, position ); + mlt_producer_seek( producer, position ); } else if ( !strcmp( eof, "pause" ) && total > 0 ) { playlist_entry *entry = this->list[ this->count - 1 ]; mlt_producer this_producer = mlt_playlist_producer( this ); - mlt_producer_seek_frame( this_producer, total - 1 ); + mlt_producer_seek( this_producer, total - 1 - mlt_producer_get_in( this_producer ) ); producer = entry->producer; - position = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - mlt_producer_seek_frame( producer, position + entry->frame_out ); + mlt_producer_seek( producer, entry->frame_out ); mlt_producer_set_speed( this_producer, 0 ); - mlt_producer_set_speed( producer, 0 ); } else if ( !strcmp( eof, "loop" ) && total > 0 ) { playlist_entry *entry = this->list[ 0 ]; mlt_producer this_producer = mlt_playlist_producer( this ); - mlt_producer_seek_frame( this_producer, 0 ); + mlt_producer_seek( this_producer, 0 ); producer = entry->producer; - position = entry->frame_in; - position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - mlt_producer_seek_frame( producer, position ); + mlt_producer_seek( producer, entry->frame_in ); } else { - mlt_producer_seek( mlt_playlist_producer( this ), 0 ); producer = &this->blank; } return producer; } +/** Invoked when a producer indicates that it has prematurely reached its end. +*/ + static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this ) { // Default producer to blank mlt_producer producer = &this->blank; // Map playlist position to real producer in virtual playlist - mlt_timecode pos = mlt_producer_position( &this->parent ); - int64_t position = mlt_producer_frame_position( &this->parent, pos ); + mlt_position position = mlt_producer_frame( &this->parent ); // Loop through the virtual playlist int i = 0; @@ -288,9 +288,9 @@ static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this ) // Seek in real producer to relative position if ( i < this->count ) { - // Update the playtime for the changed clip (hmmm) - this->list[ i ]->frame_count = position + 1; - this->list[ i ]->frame_out = position - this->list[ i ]->frame_in; + // Update the frame_count for the changed clip (hmmm) + this->list[ i ]->frame_out = position; + this->list[ i ]->frame_count = this->list[ i ]->frame_out - this->list[ i ]->frame_in + 1; // Refresh the playlist mlt_playlist_virtual_refresh( this ); @@ -299,11 +299,13 @@ static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this ) return producer; } +/** Obtain the current clips index. +*/ + int mlt_playlist_current_clip( mlt_playlist this ) { // Map playlist position to real producer in virtual playlist - mlt_timecode pos = mlt_producer_position( &this->parent ); - int64_t position = mlt_producer_frame_position( &this->parent, pos ); + mlt_position position = mlt_producer_frame( &this->parent ); // Loop through the virtual playlist int i = 0; @@ -325,6 +327,9 @@ int mlt_playlist_current_clip( mlt_playlist this ) return i; } +/** Obtain the current clips producer. +*/ + mlt_producer mlt_playlist_current( mlt_playlist this ) { int i = mlt_playlist_current_clip( this ); @@ -334,10 +339,10 @@ mlt_producer mlt_playlist_current( mlt_playlist this ) return &this->blank; } -/** Get the timecode which corresponds to the start of the next clip. +/** Get the position which corresponds to the start of the next clip. */ -mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ) +mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ) { int64_t position = 0; int absolute_clip = index; @@ -365,11 +370,11 @@ mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index else if ( absolute_clip > this->count ) absolute_clip = this->count; - // Now determine the timecode + // Now determine the position for ( i = 0; i < absolute_clip; i ++ ) position += this->list[ i ]->frame_count; - return mlt_producer_time( &this->parent, position ); + return position; } int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index ) @@ -384,10 +389,8 @@ int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, info->start = mlt_playlist_clip( this, mlt_whence_relative_start, index ); info->resource = mlt_properties_get( properties, "resource" ); info->frame_in = this->list[ index ]->frame_in; - info->in = mlt_producer_time( producer, info->frame_in ); info->frame_out = this->list[ index ]->frame_out; - info->out = mlt_producer_time( producer, info->frame_out ); - info->playtime = this->list[ index ]->playtime; + info->frame_count = this->list[ index ]->frame_count; info->length = mlt_producer_get_length( producer ); info->fps = mlt_producer_get_fps( producer ); } @@ -418,43 +421,34 @@ int mlt_playlist_clear( mlt_playlist this ) int mlt_playlist_append( mlt_playlist this, mlt_producer producer ) { // Append to virtual list - int64_t in = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) ); - int64_t out = mlt_producer_frame_position( producer, mlt_producer_get_out( producer ) ); - return mlt_playlist_virtual_append( this, producer, 0, out - in ); + return mlt_playlist_virtual_append( this, producer, 0, mlt_producer_get_playtime( producer ) - 1 ); } /** Append a producer to the playlist with in/out points. */ -int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out ) +int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out ) { // Append to virtual list if ( in != -1 && out != -1 ) - { - int64_t fin = mlt_producer_frame_position( producer, in ); - int64_t fout = mlt_producer_frame_position( producer, out ); - return mlt_playlist_virtual_append( this, producer, fin, fout ); - } + return mlt_playlist_virtual_append( this, producer, in, out ); else - { return mlt_playlist_append( this, producer ); - } } /** Append a blank to the playlist of a given length. */ -int mlt_playlist_blank( mlt_playlist this, mlt_timecode length ) +int mlt_playlist_blank( mlt_playlist this, mlt_position length ) { // Append to the virtual list - int64_t fout = mlt_producer_frame_position( &this->blank, length ); - return mlt_playlist_virtual_append( this, &this->blank, 0, fout ); + return mlt_playlist_virtual_append( this, &this->blank, 0, length ); } /** Insert a producer into the playlist. */ -int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out ) +int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out ) { return 0; } @@ -469,7 +463,10 @@ int mlt_playlist_move( mlt_playlist this, int from, int to ) return 0; } -int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out ) +/** Resize the current clip. +*/ + +int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out ) { int error = clip < 0 || clip >= this->count; if ( error == 0 ) @@ -479,23 +476,19 @@ int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_ if ( in <= -1 ) in = 0; - if ( out <= -1 || out >= mlt_producer_get_out( producer ) ) - out = mlt_producer_get_out( producer ); + if ( out <= -1 || out >= mlt_producer_get_playtime( producer ) ) + out = mlt_producer_get_playtime( producer ) - 1; if ( out < in ) { - mlt_timecode t = in; + mlt_position t = in; in = out; out = t; } - int64_t fin = mlt_producer_frame_position( producer, in ); - int64_t fout = mlt_producer_frame_position( producer, out ); - - entry->frame_in = fin; - entry->frame_out = fout; - entry->frame_count = fout - fin + 1; - entry->playtime = out - in; + entry->frame_in = in; + entry->frame_out = out; + entry->frame_count = out - in + 1; mlt_playlist_virtual_refresh( this ); } return error; @@ -529,8 +522,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i notifier( argument ); } - // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + // Update position on the frame we're creating + mlt_frame_set_position( *frame, mlt_producer_frame( producer ) ); // Position ourselves on the next frame mlt_producer_prepare_next( producer ); diff --git a/src/framework/mlt_playlist.h b/src/framework/mlt_playlist.h index 8cdccce..dd88959 100644 --- a/src/framework/mlt_playlist.h +++ b/src/framework/mlt_playlist.h @@ -29,14 +29,12 @@ typedef struct { mlt_producer producer; - mlt_timecode start; + mlt_position start; char *resource; - mlt_timecode in; - int64_t frame_in; - mlt_timecode out; - int64_t frame_out; - mlt_timecode playtime; - mlt_timecode length; + mlt_position frame_in; + mlt_position frame_out; + mlt_position frame_count; + mlt_position length; float fps; } mlt_playlist_clip_info; @@ -51,16 +49,16 @@ extern mlt_properties mlt_playlist_properties( mlt_playlist this ); extern int mlt_playlist_count( mlt_playlist this ); extern int mlt_playlist_clear( mlt_playlist this ); extern int mlt_playlist_append( mlt_playlist this, mlt_producer producer ); -extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out ); -extern int mlt_playlist_blank( mlt_playlist this, mlt_timecode length ); -extern mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ); +extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out ); +extern int mlt_playlist_blank( mlt_playlist this, mlt_position length ); +extern mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index ); extern int mlt_playlist_current_clip( mlt_playlist this ); extern mlt_producer mlt_playlist_current( mlt_playlist this ); extern int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index ); -extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out ); +extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out ); extern int mlt_playlist_remove( mlt_playlist this, int where ); extern int mlt_playlist_move( mlt_playlist this, int from, int to ); -extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out ); +extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out ); extern void mlt_playlist_close( mlt_playlist this ); #endif diff --git a/src/framework/mlt_producer.c b/src/framework/mlt_producer.c index 278d902..c874243 100644 --- a/src/framework/mlt_producer.c +++ b/src/framework/mlt_producer.c @@ -53,14 +53,13 @@ int mlt_producer_init( mlt_producer this, void *child ) // Set the default properties mlt_properties_set( properties, "mlt_type", "mlt_producer" ); - mlt_properties_set_timecode( properties, "position", 0.0 ); + mlt_properties_set_position( properties, "position", 0.0 ); mlt_properties_set_double( properties, "frame", 0 ); mlt_properties_set_double( properties, "fps", 25.0 ); mlt_properties_set_double( properties, "speed", 1.0 ); - mlt_properties_set_timecode( properties, "in", 0.0 ); - mlt_properties_set_timecode( properties, "out", 36000.0 ); - mlt_properties_set_timecode( properties, "length", 36000.0 ); - mlt_properties_set_int( properties, "known_length", 1 ); + mlt_properties_set_position( properties, "in", 0.0 ); + mlt_properties_set_position( properties, "out", 179999 ); + mlt_properties_set_position( properties, "length", 180000 ); mlt_properties_set_double( properties, "aspect_ratio", 4.0 / 3.0 ); mlt_properties_set( properties, "log_id", "multitrack" ); @@ -87,92 +86,64 @@ mlt_properties mlt_producer_properties( mlt_producer this ) return mlt_service_properties( &this->parent ); } -/** Convert frame position to timecode. +/** Convert frame position to position. */ -mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame ) +/* +mlt_position mlt_producer_time( mlt_producer this, int64_t frame ) { if ( frame < 0 ) return -1; else - return ( mlt_timecode )frame / mlt_producer_get_fps( this ); + return ( mlt_position )frame / mlt_producer_get_fps( this ); } +*/ -/** Convert timecode to frame position. +/** Convert position to frame position. */ -int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position ) +/* +int64_t mlt_producer_frame_position( mlt_producer this, mlt_position position ) { if ( position < 0 ) return -1; else return ( int64_t )( floor( position * mlt_producer_get_fps( this ) + 0.5 ) ); } +*/ -/** Seek to a specified time code. +/** Seek to a specified position. */ -int mlt_producer_seek( mlt_producer this, mlt_timecode timecode ) +int mlt_producer_seek( mlt_producer this, mlt_position position ) { // Check bounds - if ( timecode < 0 ) - timecode = 0; - if ( timecode > mlt_producer_get_playtime( this ) ) - timecode = mlt_producer_get_playtime( this ); + if ( position < 0 ) + position = 0; + else if ( position > mlt_producer_get_playtime( this ) ) + position = mlt_producer_get_playtime( this ) - 1; // Set the position - mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode ); + mlt_properties_set_position( mlt_producer_properties( this ), "position", position ); // Calculate the absolute frame - double frame = ( mlt_producer_get_in( this ) + timecode ) * mlt_producer_get_fps( this ); - mlt_properties_set_double( mlt_producer_properties( this ), "frame", floor( frame + 0.5 ) ); - - return 0; -} - -/** Seek to a specified absolute frame. -*/ - -int mlt_producer_seek_frame( mlt_producer this, int64_t frame ) -{ - // Calculate the time code - double timecode = ( frame / mlt_producer_get_fps( this ) ) - mlt_producer_get_in( this ); - - // If timecode is invalid, then seek on time - if ( frame < 0 || timecode < 0 ) - { - // Seek to the in point - mlt_producer_seek( this, 0 ); - } - else if ( timecode > mlt_producer_get_playtime( this ) ) - { - // Seek to the out point - mlt_producer_seek( this, mlt_producer_get_playtime( this ) ); - } - else - { - // Set the position - mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode ); - - // Set the absolute frame - mlt_properties_set_double( mlt_producer_properties( this ), "frame", frame ); - } + mlt_properties_set_position( mlt_producer_properties( this ), "frame", mlt_producer_get_in( this ) + position ); return 0; } -/** Get the current time code. +/** Get the current position (relative to in point). */ -mlt_timecode mlt_producer_position( mlt_producer this ) +mlt_position mlt_producer_position( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "position" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "position" ); } -/** Get the current frame. +/** Get the current position (relative to start of producer). */ -uint64_t mlt_producer_frame( mlt_producer this ) +mlt_position mlt_producer_frame( mlt_producer this ) { return mlt_properties_get_double( mlt_producer_properties( this ), "frame" ); } @@ -204,32 +175,30 @@ double mlt_producer_get_fps( mlt_producer this ) /** Set the in and out points. */ -int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out ) +int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out ) { // Correct ins and outs if necessary if ( in < 0 ) in = 0; - if ( in > mlt_producer_get_length( this ) ) + else if ( in > mlt_producer_get_length( this ) ) in = mlt_producer_get_length( this ); + if ( out < 0 ) out = 0; - if ( out > mlt_producer_get_length( this ) ) + else if ( out > mlt_producer_get_length( this ) ) out = mlt_producer_get_length( this ); // Swap ins and outs if wrong if ( out < in ) { - mlt_timecode t = in; + mlt_position t = in; in = out; out = t; } // Set the values - mlt_properties_set_timecode( mlt_producer_properties( this ), "in", in ); - mlt_properties_set_timecode( mlt_producer_properties( this ), "out", out ); - - // Seek to the in point - mlt_producer_seek( this, 0 ); + mlt_properties_set_position( mlt_producer_properties( this ), "in", in ); + mlt_properties_set_position( mlt_producer_properties( this ), "out", out ); return 0; } @@ -237,33 +206,33 @@ int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecod /** Get the in point. */ -mlt_timecode mlt_producer_get_in( mlt_producer this ) +mlt_position mlt_producer_get_in( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "in" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "in" ); } /** Get the out point. */ -mlt_timecode mlt_producer_get_out( mlt_producer this ) +mlt_position mlt_producer_get_out( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "out" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "out" ); } /** Get the total play time. */ -mlt_timecode mlt_producer_get_playtime( mlt_producer this ) +mlt_position mlt_producer_get_playtime( mlt_producer this ) { - return mlt_producer_get_out( this ) - mlt_producer_get_in( this ); + return mlt_producer_get_out( this ) - mlt_producer_get_in( this ) + 1; } /** Get the total length of the producer. */ -mlt_timecode mlt_producer_get_length( mlt_producer this ) +mlt_position mlt_producer_get_length( mlt_producer this ) { - return mlt_properties_get_timecode( mlt_producer_properties( this ), "length" ); + return mlt_properties_get_position( mlt_producer_properties( this ), "length" ); } /** Prepare for next frame. @@ -271,7 +240,7 @@ mlt_timecode mlt_producer_get_length( mlt_producer this ) void mlt_producer_prepare_next( mlt_producer this ) { - mlt_producer_seek_frame( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) ); + mlt_producer_seek( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) ); } /** Get a frame. @@ -287,26 +256,24 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind { // Get the frame from the implementation result = this->get_frame( this, frame, index ); - - mlt_properties frame_properties = mlt_frame_properties( *frame ); - double speed = mlt_producer_get_speed( this ); - mlt_properties_set_double( frame_properties, "speed", speed ); } else { // Generate a test frame *frame = mlt_frame_init( ); - // Set the timecode - result = mlt_frame_set_timecode( *frame, mlt_producer_position( this ) ); + // Set the position + result = mlt_frame_set_position( *frame, mlt_producer_position( this ) ); - // Calculate the next timecode + // Calculate the next position mlt_producer_prepare_next( this ); } - // Copy the fps of the producer onto the frame + // Copy the fps and speed of the producer onto the frame mlt_properties properties = mlt_frame_properties( *frame ); mlt_properties_set_double( properties, "fps", mlt_producer_get_fps( this ) ); + double speed = mlt_producer_get_speed( this ); + mlt_properties_set_double( properties, "speed", speed ); return 0; } diff --git a/src/framework/mlt_producer.h b/src/framework/mlt_producer.h index 5297652..7e748c0 100644 --- a/src/framework/mlt_producer.h +++ b/src/framework/mlt_producer.h @@ -43,23 +43,23 @@ struct mlt_producer_s /** Public final methods */ +//extern double mlt_producer_convert_position_to_time( mlt_producer this, int64_t frame ); +//extern mlt_position mlt_producer_convert_time_to_position( mlt_producer this, double time ); + extern int mlt_producer_init( mlt_producer this, void *child ); extern mlt_service mlt_producer_service( mlt_producer this ); extern mlt_properties mlt_producer_properties( mlt_producer this ); -extern mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame ); -extern int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position ); -extern int mlt_producer_seek( mlt_producer this, mlt_timecode timecode ); -extern int mlt_producer_seek_frame( mlt_producer this, int64_t frame ); -extern mlt_timecode mlt_producer_position( mlt_producer this ); -extern uint64_t mlt_producer_frame( mlt_producer this ); +extern int mlt_producer_seek( mlt_producer this, mlt_position position ); +extern mlt_position mlt_producer_position( mlt_producer this ); +extern mlt_position mlt_producer_frame( mlt_producer this ); extern int mlt_producer_set_speed( mlt_producer this, double speed ); extern double mlt_producer_get_speed( mlt_producer this ); extern double mlt_producer_get_fps( mlt_producer this ); -extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out ); -extern mlt_timecode mlt_producer_get_in( mlt_producer this ); -extern mlt_timecode mlt_producer_get_out( mlt_producer this ); -extern mlt_timecode mlt_producer_get_playtime( mlt_producer this ); -extern mlt_timecode mlt_producer_get_length( mlt_producer this ); +extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out ); +extern mlt_position mlt_producer_get_in( mlt_producer this ); +extern mlt_position mlt_producer_get_out( mlt_producer this ); +extern mlt_position mlt_producer_get_playtime( mlt_producer this ); +extern mlt_position mlt_producer_get_length( mlt_producer this ); extern void mlt_producer_prepare_next( mlt_producer this ); extern void mlt_producer_close( mlt_producer this ); diff --git a/src/framework/mlt_properties.c b/src/framework/mlt_properties.c index 679d97a..d047da0 100644 --- a/src/framework/mlt_properties.c +++ b/src/framework/mlt_properties.c @@ -285,16 +285,16 @@ int mlt_properties_set_double( mlt_properties this, char *name, double value ) /** Get a value associated to the name. */ -mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name ) +mlt_position mlt_properties_get_position( mlt_properties this, char *name ) { mlt_property value = mlt_properties_find( this, name ); - return value == NULL ? 0 : mlt_property_get_timecode( value ); + return value == NULL ? 0 : mlt_property_get_position( value ); } /** Set a value associated to the name. */ -int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value ) +int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value ) { int error = 1; @@ -303,7 +303,7 @@ int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode v // Set it if not NULL if ( property != NULL ) - error = mlt_property_set_timecode( property, value ); + error = mlt_property_set_position( property, value ); return error; } diff --git a/src/framework/mlt_properties.h b/src/framework/mlt_properties.h index 540b7ae..2cacc9f 100644 --- a/src/framework/mlt_properties.h +++ b/src/framework/mlt_properties.h @@ -48,8 +48,8 @@ extern int mlt_properties_get_int( mlt_properties this, char *name ); extern int mlt_properties_set_int( mlt_properties this, char *name, int value ); extern double mlt_properties_get_double( mlt_properties this, char *name ); extern int mlt_properties_set_double( mlt_properties this, char *name, double value ); -extern mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name ); -extern int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value ); +extern mlt_position mlt_properties_get_position( mlt_properties this, char *name ); +extern int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value ); extern int mlt_properties_set_data( mlt_properties this, char *name, void *value, int length, mlt_destructor, mlt_serialiser ); extern void *mlt_properties_get_data( mlt_properties this, char *name, int *length ); extern int mlt_properties_count( mlt_properties this ); diff --git a/src/framework/mlt_property.c b/src/framework/mlt_property.c index f471b18..0a47529 100644 --- a/src/framework/mlt_property.c +++ b/src/framework/mlt_property.c @@ -73,14 +73,14 @@ int mlt_property_set_double( mlt_property this, double value ) return 0; } -/** Set a timecode on this property. +/** Set a position on this property. */ -int mlt_property_set_timecode( mlt_property this, mlt_timecode value ) +int mlt_property_set_position( mlt_property this, mlt_position value ) { mlt_property_clear( this ); - this->types = mlt_prop_timecode; - this->prop_timecode = value; + this->types = mlt_prop_position; + this->prop_position = value; return 0; } @@ -132,8 +132,8 @@ int mlt_property_get_int( mlt_property this ) return this->prop_int; else if ( this->types & mlt_prop_double ) return ( int )this->prop_double; - else if ( this->types & mlt_prop_timecode ) - return ( int )this->prop_timecode; + else if ( this->types & mlt_prop_position ) + return ( int )this->prop_position; else if ( this->types & mlt_prop_int64 ) return ( int )this->prop_int64; else if ( this->types & mlt_prop_string ) @@ -150,8 +150,8 @@ double mlt_property_get_double( mlt_property this ) return this->prop_double; else if ( this->types & mlt_prop_int ) return ( double )this->prop_int; - else if ( this->types & mlt_prop_timecode ) - return ( double )this->prop_timecode; + else if ( this->types & mlt_prop_position ) + return ( double )this->prop_position; else if ( this->types & mlt_prop_int64 ) return ( double )this->prop_int64; else if ( this->types & mlt_prop_string ) @@ -159,21 +159,21 @@ double mlt_property_get_double( mlt_property this ) return 0; } -/** Get a timecode from this property. +/** Get a position from this property. */ -mlt_timecode mlt_property_get_timecode( mlt_property this ) +mlt_position mlt_property_get_position( mlt_property this ) { - if ( this->types & mlt_prop_timecode ) - return this->prop_timecode; + if ( this->types & mlt_prop_position ) + return this->prop_position; else if ( this->types & mlt_prop_int ) - return ( mlt_timecode )this->prop_int; + return ( mlt_position )this->prop_int; else if ( this->types & mlt_prop_double ) - return ( mlt_timecode )this->prop_double; + return ( mlt_position )this->prop_double; else if ( this->types & mlt_prop_int64 ) - return ( mlt_timecode )this->prop_int64; + return ( mlt_position )this->prop_int64; else if ( this->types & mlt_prop_string ) - return ( mlt_timecode )atof( this->prop_string ); + return ( mlt_position )atol( this->prop_string ); return 0; } @@ -188,10 +188,10 @@ int64_t mlt_property_get_int64( mlt_property this ) return ( int64_t )this->prop_int; else if ( this->types & mlt_prop_double ) return ( int64_t )this->prop_double; - else if ( this->types & mlt_prop_timecode ) - return ( int64_t )this->prop_timecode; + else if ( this->types & mlt_prop_position ) + return ( int64_t )this->prop_position; else if ( this->types & mlt_prop_string ) - return ( int64_t )atof( this->prop_string ); + return ( int64_t )atol( this->prop_string ); return 0; } @@ -215,11 +215,11 @@ char *mlt_property_get_string( mlt_property this ) this->prop_string = malloc( 32 ); sprintf( this->prop_string, "%e", this->prop_double ); } - else if ( this->types & mlt_prop_timecode ) + else if ( this->types & mlt_prop_position ) { this->types |= mlt_prop_string; this->prop_string = malloc( 32 ); - sprintf( this->prop_string, "%e", this->prop_timecode ); + sprintf( this->prop_string, "%lld", this->prop_position ); } else if ( this->types & mlt_prop_int64 ) { diff --git a/src/framework/mlt_property.h b/src/framework/mlt_property.h index 6b0def5..3f59ad2 100644 --- a/src/framework/mlt_property.h +++ b/src/framework/mlt_property.h @@ -31,7 +31,7 @@ typedef enum mlt_prop_none = 0, mlt_prop_int = 1, mlt_prop_string = 2, - mlt_prop_timecode = 4, + mlt_prop_position = 4, mlt_prop_double = 8, mlt_prop_data = 16, mlt_prop_int64 = 32 @@ -48,7 +48,7 @@ typedef struct mlt_property_s // Atomic type handling int prop_int; - mlt_timecode prop_timecode; + mlt_position prop_position; double prop_double; int64_t prop_int64; @@ -70,13 +70,13 @@ extern mlt_property mlt_property_init( ); extern void mlt_property_clear( mlt_property this ); extern int mlt_property_set_int( mlt_property this, int value ); extern int mlt_property_set_double( mlt_property this, double value ); -extern int mlt_property_set_timecode( mlt_property this, mlt_timecode value ); +extern int mlt_property_set_position( mlt_property this, mlt_position value ); extern int mlt_property_set_uint64( mlt_property this, uint64_t value ); extern int mlt_property_set_string( mlt_property this, char *value ); extern int mlt_property_set_data( mlt_property this, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser ); extern int mlt_property_get_int( mlt_property this ); extern double mlt_property_get_double( mlt_property this ); -extern mlt_timecode mlt_property_get_timecode( mlt_property this ); +extern mlt_position mlt_property_get_position( mlt_property this ); extern int64_t mlt_property_get_int64( mlt_property this ); extern char *mlt_property_get_string( mlt_property this ); extern void *mlt_property_get_data( mlt_property this, int *length ); diff --git a/src/framework/mlt_tractor.c b/src/framework/mlt_tractor.c index f4b77c4..6c02230 100644 --- a/src/framework/mlt_tractor.c +++ b/src/framework/mlt_tractor.c @@ -22,6 +22,7 @@ #include "mlt_tractor.h" #include "mlt_frame.h" +#include "mlt_multitrack.h" #include #include @@ -31,14 +32,14 @@ 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 ); /** Constructor for the tractor. @@ -50,10 +51,10 @@ 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; + producer->get_frame = producer_get_frame; } else { @@ -69,21 +70,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 +108,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; @@ -105,6 +120,25 @@ static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track int done = 0; mlt_frame temp; + // Get the properties of the parent producer + mlt_properties properties = mlt_producer_properties( parent ); + + // Try to obtain the multitrack associated to the tractor + mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", 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 ) ); + mlt_producer_set_in_and_out( parent, mlt_producer_get_in( target ), mlt_producer_get_out( target ) ); + } + else + { + fprintf( stderr, "tractor without a multitrack!!\n" ); + } + // Loop through each of the tracks we're harvesting for ( i = 0; !done; i ++ ) { @@ -133,6 +167,9 @@ static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track } } + // Prepare the next frame + mlt_producer_prepare_next( parent ); + // Indicate our found status return 0; } @@ -149,7 +186,7 @@ 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 ); + mlt_producer_close( &this->parent ); free( this ); } diff --git a/src/framework/mlt_tractor.h b/src/framework/mlt_tractor.h index 28a6071..b6576ec 100644 --- a/src/framework/mlt_tractor.h +++ b/src/framework/mlt_tractor.h @@ -25,6 +25,8 @@ extern mlt_tractor mlt_tractor_init( ); extern mlt_service mlt_tractor_service( mlt_tractor this ); +extern mlt_producer mlt_tractor_producer( mlt_tractor this ); +extern mlt_properties mlt_tractor_properties( mlt_tractor this ); extern int mlt_tractor_connect( mlt_tractor this, mlt_service service ); extern void mlt_tractor_close( mlt_tractor this ); diff --git a/src/framework/mlt_transition.c b/src/framework/mlt_transition.c index de416a8..5071550 100644 --- a/src/framework/mlt_transition.c +++ b/src/framework/mlt_transition.c @@ -46,8 +46,8 @@ int mlt_transition_init( mlt_transition this, void *child ) service->get_frame = transition_get_frame; - mlt_properties_set_timecode( properties, "in", 0 ); - mlt_properties_set_timecode( properties, "out", 0 ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", 0 ); mlt_properties_set_int( properties, "a_track", 0 ); mlt_properties_set_int( properties, "b_track", 1 ); @@ -91,11 +91,11 @@ int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_tra /** Set the in and out points. */ -void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out ) +void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out ) { mlt_properties properties = mlt_transition_properties( this ); - mlt_properties_set_timecode( properties, "in", in ); - mlt_properties_set_timecode( properties, "out", out ); + mlt_properties_set_position( properties, "in", in ); + mlt_properties_set_position( properties, "out", out ); } /** Get the index of the a track. @@ -119,19 +119,19 @@ int mlt_transition_get_b_track( mlt_transition this ) /** Get the in point. */ -mlt_timecode mlt_transition_get_in( mlt_transition this ) +mlt_position mlt_transition_get_in( mlt_transition this ) { mlt_properties properties = mlt_transition_properties( this ); - return mlt_properties_get_timecode( properties, "in" ); + return mlt_properties_get_position( properties, "in" ); } /** Get the out point. */ -mlt_timecode mlt_transition_get_out( mlt_transition this ) +mlt_position mlt_transition_get_out( mlt_transition this ) { mlt_properties properties = mlt_transition_properties( this ); - return mlt_properties_get_timecode( properties, "out" ); + return mlt_properties_get_position( properties, "out" ); } /** Process the frame. @@ -183,8 +183,8 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i int a_track = mlt_properties_get_int( properties, "a_track" ); int b_track = mlt_properties_get_int( properties, "b_track" ); - mlt_timecode in = mlt_properties_get_timecode( properties, "in" ); - mlt_timecode out = mlt_properties_get_timecode( properties, "out" ); + mlt_position in = mlt_properties_get_position( properties, "in" ); + mlt_position out = mlt_properties_get_position( properties, "out" ); // Fetch a and b frames together... if ( ( index == a_track || index == b_track ) && @@ -198,8 +198,8 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i if ( index == a_track ) { // Determine if we're in the right time zone - mlt_timecode timecode = mlt_frame_get_timecode( this->a_frame ); - if ( timecode >= in && timecode < out ) + mlt_position position = mlt_frame_get_position( this->a_frame ); + if ( position >= in && position < out ) { // Process the transition *frame = transition_process( this, this->a_frame, this->b_frame ); @@ -225,8 +225,8 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i } else { - mlt_timecode timecode = mlt_frame_get_timecode( this->b_frame ); - if ( timecode >= in && timecode < out ) + mlt_position position = mlt_frame_get_position( this->b_frame ); + if ( position >= in && position < out ) { // We're in the zone, but the 'a frame' has not been requested yet *frame = mlt_frame_init( ); diff --git a/src/framework/mlt_transition.h b/src/framework/mlt_transition.h index 7ac765c..c297bdb 100644 --- a/src/framework/mlt_transition.h +++ b/src/framework/mlt_transition.h @@ -55,11 +55,11 @@ extern int mlt_transition_init( mlt_transition this, void *child ); extern mlt_service mlt_transition_service( mlt_transition this ); extern mlt_properties mlt_transition_properties( mlt_transition this ); extern int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track ); -extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out ); +extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out ); extern int mlt_transition_get_a_track( mlt_transition this ); extern int mlt_transition_get_b_track( mlt_transition this ); -extern mlt_timecode mlt_transition_get_in( mlt_transition this ); -extern mlt_timecode mlt_transition_get_out( mlt_transition this ); +extern mlt_position mlt_transition_get_in( mlt_transition this ); +extern mlt_position mlt_transition_get_out( mlt_transition this ); extern void mlt_transition_close( mlt_transition this ); #endif diff --git a/src/framework/mlt_types.h b/src/framework/mlt_types.h index b100f18..162602f 100644 --- a/src/framework/mlt_types.h +++ b/src/framework/mlt_types.h @@ -31,7 +31,7 @@ typedef enum } mlt_whence; -typedef double mlt_timecode; +typedef int64_t mlt_position; typedef struct mlt_frame_s *mlt_frame, **mlt_frame_ptr; typedef struct mlt_properties_s *mlt_properties; typedef struct mlt_service_s *mlt_service; diff --git a/src/inigo/inigo.c b/src/inigo/inigo.c index 2dbda0e..fa76e64 100644 --- a/src/inigo/inigo.c +++ b/src/inigo/inigo.c @@ -50,43 +50,57 @@ static void transport_action( mlt_producer producer, char *value ) case '9': mlt_producer_set_speed( producer, 10 ); break; + case 'd': + if ( multitrack != NULL ) + { + int i = 0; + mlt_position last = -1; + for ( i = 0; 1; i ++ ) + { + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_start, i ); + if ( time == last ) + break; + last = time; + fprintf( stderr, "%d: %lld\n", i, time ); + } + } + break; + case 'g': if ( multitrack != NULL ) { - mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 ); + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 ); mlt_producer_seek( producer, time ); } break; case 'h': if ( multitrack != NULL ) { - mlt_producer producer = mlt_multitrack_producer( multitrack ); - int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) ); + mlt_position position = mlt_producer_position( producer ); mlt_producer_set_speed( producer, 0 ); - mlt_producer_seek_frame( producer, position - 1 >= 0 ? position - 1 : 0 ); + mlt_producer_seek( producer, position - 1 >= 0 ? position - 1 : 0 ); } break; case 'j': if ( multitrack != NULL ) { - mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 ); + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 ); mlt_producer_seek( producer, time ); } break; case 'k': if ( multitrack != NULL ) { - mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 ); + mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 ); mlt_producer_seek( producer, time ); } break; case 'l': if ( multitrack != NULL ) { - mlt_producer producer = mlt_multitrack_producer( multitrack ); - int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) ); + mlt_position position = mlt_producer_position( producer ); mlt_producer_set_speed( producer, 0 ); - mlt_producer_seek_frame( producer, position + 1 ); + mlt_producer_seek( producer, position + 1 ); } break; } diff --git a/src/miracle/miracle_unit.c b/src/miracle/miracle_unit.c index 479ed71..a1043df 100644 --- a/src/miracle/miracle_unit.c +++ b/src/miracle/miracle_unit.c @@ -218,7 +218,6 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response ) mlt_properties properties = unit->properties; int generation = mlt_properties_get_int( properties, "generation" ); mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_producer producer = mlt_playlist_producer( playlist ); valerie_response_printf( response, 1024, "%d\n", generation ); @@ -230,8 +229,8 @@ void miracle_unit_report_list( miracle_unit unit, valerie_response response ) i, info.resource, info.frame_in, info.frame_out, - mlt_producer_frame_position( producer, info.playtime ), - mlt_producer_frame_position( producer, info.length ), + info.frame_count, + info.length, info.fps ); } } @@ -257,7 +256,7 @@ valerie_error_code miracle_unit_load( miracle_unit unit, char *clip, int64_t in, { mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) ); + mlt_playlist_append_io( playlist, instance, in, out ); miracle_log( LOG_DEBUG, "loaded clip %s", clip ); miracle_unit_status_communicate( unit ); return valerie_ok; @@ -274,7 +273,7 @@ valerie_error_code miracle_unit_insert( miracle_unit unit, char *clip, int index { mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_playlist_insert( playlist, instance, index, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) ); + mlt_playlist_insert( playlist, instance, index, in, out ); miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index ); update_generation( unit ); miracle_unit_status_communicate( unit ); @@ -330,7 +329,7 @@ valerie_error_code miracle_unit_append( miracle_unit unit, char *clip, int64_t i { mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); - mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) ); + mlt_playlist_append_io( playlist, instance, in, out ); miracle_log( LOG_DEBUG, "appended clip %s", clip ); update_generation( unit ); miracle_unit_status_communicate( unit ); @@ -424,13 +423,13 @@ int miracle_unit_get_status( miracle_unit unit, valerie_status status ) status->fps = mlt_producer_get_fps( producer ); status->in = info.frame_in; status->out = info.frame_out; - status->position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) ); - status->length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) ); + status->position = mlt_producer_position( clip ); + status->length = mlt_producer_get_length( clip ); strncpy( status->tail_clip, info.resource, sizeof( status->tail_clip ) ); status->tail_in = info.frame_in; status->tail_out = info.frame_out; - status->tail_position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) ); - status->tail_length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) ); + status->tail_position = mlt_producer_position( clip ); + status->tail_length = mlt_producer_get_length( clip ); status->clip_index = mlt_playlist_current_clip( playlist ); status->seek_flag = 1; } @@ -477,7 +476,7 @@ void miracle_unit_change_position( miracle_unit unit, int clip, int64_t position if ( mlt_playlist_get_clip_info( playlist, &info, clip ) == 0 ) { - int64_t frame_start = mlt_producer_frame_position( info.producer, info.start ); + int64_t frame_start = info.start; int64_t frame_offset = position; if ( frame_offset < 0 ) @@ -487,7 +486,7 @@ void miracle_unit_change_position( miracle_unit unit, int clip, int64_t position if ( frame_offset >= info.frame_out ) frame_offset = info.frame_out; - mlt_producer_seek_frame( producer, frame_start + frame_offset - info.frame_in ); + mlt_producer_seek( producer, frame_start + frame_offset - info.frame_in ); } miracle_unit_status_communicate( unit ); @@ -516,8 +515,8 @@ int miracle_unit_set_clip_in( miracle_unit unit, int index, int64_t position ) if ( error == 0 ) { - mlt_timecode in = mlt_producer_time( info.producer, position ); - error = mlt_playlist_resize_clip( playlist, index, in, info.out ); + miracle_unit_play( unit, 0 ); + error = mlt_playlist_resize_clip( playlist, index, position, info.frame_out ); update_generation( unit ); miracle_unit_change_position( unit, index, 0 ); } @@ -537,8 +536,8 @@ int miracle_unit_set_clip_out( miracle_unit unit, int index, int64_t position ) if ( error == 0 ) { - mlt_timecode out = mlt_producer_time( info.producer, position ); - error = mlt_playlist_resize_clip( playlist, index, info.in, out ); + miracle_unit_play( unit, 0 ); + error = mlt_playlist_resize_clip( playlist, index, info.frame_in, position ); update_generation( unit ); miracle_unit_status_communicate( unit ); miracle_unit_change_position( unit, index, -1 ); @@ -555,8 +554,8 @@ void miracle_unit_step( miracle_unit unit, int64_t offset ) mlt_properties properties = unit->properties; mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL ); mlt_producer producer = mlt_playlist_producer( playlist ); - mlt_timecode position = mlt_producer_position( producer ); - mlt_producer_seek_frame( producer, mlt_producer_frame_position( producer, position ) + offset ); + mlt_position position = mlt_producer_frame( producer ); + mlt_producer_seek( producer, position + offset ); } /** Set the unit's clip mode regarding in and out points. diff --git a/src/modules/core/producer_ppm.c b/src/modules/core/producer_ppm.c index b508654..c929d25 100644 --- a/src/modules/core/producer_ppm.c +++ b/src/modules/core/producer_ppm.c @@ -249,7 +249,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i ( *frame )->get_audio = producer_get_audio; // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/src/modules/core/transition_composite.c b/src/modules/core/transition_composite.c index 7bcdfa9..c2ba62d 100644 --- a/src/modules/core/transition_composite.c +++ b/src/modules/core/transition_composite.c @@ -44,32 +44,42 @@ static int transition_get_image( mlt_frame this, uint8_t **image, mlt_image_form // Get the b frame from the stack mlt_frame b_frame = mlt_frame_pop_frame( this ); - // Get the properties of the b frame - mlt_properties b_props = mlt_frame_properties( b_frame ); - - // Arbitrary composite defaults - int x = 0; - int y = 0; - double mix = 1.0; - - // Override from b frame properties if provided - if ( mlt_properties_get( b_props, "x" ) != NULL ) - x = mlt_properties_get_int( b_props, "x" ); - if ( mlt_properties_get( b_props, "y" ) != NULL ) - y = mlt_properties_get_int( b_props, "y" ); - if ( mlt_properties_get( b_props, "mix" ) != NULL ) - mix = mlt_properties_get_double( b_props, "mix" ); - - // Composite the b_frame on the a_frame - mlt_frame_composite_yuv( this, b_frame, x, y, mix ); - - // Extract the a_frame image info - *width = mlt_properties_get_int( a_props, "width" ); - *height = mlt_properties_get_int( a_props, "height" ); - *image = mlt_properties_get_data( a_props, "image", NULL ); - - // Close the b_frame - mlt_frame_close( b_frame ); + if ( b_frame != NULL ) + { + // Get the properties of the b frame + mlt_properties b_props = mlt_frame_properties( b_frame ); + + // Arbitrary composite defaults + int x = 0; + int y = 0; + double mix = 1.0; + + // Override from b frame properties if provided + if ( mlt_properties_get( b_props, "x" ) != NULL ) + x = mlt_properties_get_int( b_props, "x" ); + if ( mlt_properties_get( b_props, "y" ) != NULL ) + y = mlt_properties_get_int( b_props, "y" ); + if ( mlt_properties_get( b_props, "mix" ) != NULL ) + mix = mlt_properties_get_double( b_props, "mix" ); + + // Composite the b_frame on the a_frame + mlt_frame_composite_yuv( this, b_frame, x, y, mix ); + + // Extract the a_frame image info + *width = mlt_properties_get_int( a_props, "width" ); + *height = mlt_properties_get_int( a_props, "height" ); + *image = mlt_properties_get_data( a_props, "image", NULL ); + + // Close the b_frame + mlt_frame_close( b_frame ); + } + else if ( a_props != NULL ) + { + // Extract the a_frame image info + *width = mlt_properties_get_int( a_props, "width" ); + *height = mlt_properties_get_int( a_props, "height" ); + *image = mlt_properties_get_data( a_props, "image", NULL ); + } return 0; } diff --git a/src/modules/core/transition_luma.c b/src/modules/core/transition_luma.c index a3ae3dc..71c8238 100644 --- a/src/modules/core/transition_luma.c +++ b/src/modules/core/transition_luma.c @@ -339,9 +339,9 @@ static mlt_frame transition_process( mlt_transition transition, mlt_frame a_fram } // Determine the time position of this frame in the transition duration - mlt_timecode in = mlt_transition_get_in( transition ); - mlt_timecode out = mlt_transition_get_out( transition ); - mlt_timecode time = mlt_frame_get_timecode( b_frame ); + mlt_position in = mlt_transition_get_in( transition ); + mlt_position out = mlt_transition_get_out( transition ); + mlt_position time = mlt_frame_get_position( b_frame ); double pos = ( time - in ) / ( out - in ); // Set the b frame properties diff --git a/src/modules/dv/Makefile b/src/modules/dv/Makefile index 218f85b..f3aac3c 100644 --- a/src/modules/dv/Makefile +++ b/src/modules/dv/Makefile @@ -2,7 +2,8 @@ TARGET = ../libmltdv.so OBJS = factory.o \ - producer_libdv.o + producer_libdv.o \ + consumer_libdv.o CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread diff --git a/src/modules/dv/configure b/src/modules/dv/configure index 876897c..9453267 100755 --- a/src/modules/dv/configure +++ b/src/modules/dv/configure @@ -7,5 +7,9 @@ cat << EOF >> ../producers.dat libdv libmltdv.so EOF +cat << EOF >> ../consumers.dat +libdv libmltdv.so +EOF + fi diff --git a/src/modules/dv/consumer_libdv.c b/src/modules/dv/consumer_libdv.c new file mode 100644 index 0000000..07bd6e6 --- /dev/null +++ b/src/modules/dv/consumer_libdv.c @@ -0,0 +1,329 @@ +/* + * producer_libdv.c -- a DV encoder based on libdv + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// Local header files +#include "consumer_libdv.h" + +// mlt Header files +#include + +// System header files +#include +#include +#include +#include + +// libdv header files +#include + +// Forward references. +static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ); +static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ); +static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame ); +static void *consumer_thread( void *arg ); +static void consumer_close( mlt_consumer this ); + +/** Initialise the dv consumer. +*/ + +mlt_consumer consumer_libdv_init( char *arg ) +{ + // Allocate the consumer + mlt_consumer this = calloc( 1, sizeof( struct mlt_consumer_s ) ); + + // If memory allocated and initialises without error + if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 ) + { + // Get properties from the consumer + mlt_properties properties = mlt_consumer_properties( this ); + + // Allocate a thread + pthread_t *thread = calloc( 1, sizeof( pthread_t ) ); + + // Assign close callback + this->close = consumer_close; + + // Assign all properties + if ( arg == NULL || !strcmp( arg, "PAL" ) ) + mlt_properties_set_double( properties, "fps", 25 ); + else + mlt_properties_set_double( properties, "fps", 29.97 ); + + mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL ); + mlt_properties_set_data( properties, "video", consumer_encode_video, 0, NULL, NULL ); + mlt_properties_set_data( properties, "audio", consumer_encode_audio, 0, NULL, NULL ); + mlt_properties_set_data( properties, "output", consumer_output, 0, NULL, NULL ); + + // Create the thread (this should not happen immediately) + mlt_properties_set_int( properties, "running", 1 ); + pthread_create( thread, NULL, consumer_thread, this ); + } + else + { + // Clean up in case of init failure + free( this ); + this = NULL; + } + + // Return this + return this; +} + +/** Get or create a new libdv encoder. +*/ + +static dv_encoder_t *libdv_get_encoder( mlt_consumer this, mlt_frame frame ) +{ + // Get the properties of the consumer + mlt_properties this_properties = mlt_consumer_properties( this ); + + // Obtain the dv_encoder + dv_encoder_t *encoder = mlt_properties_get_data( this_properties, "dv_encoder", NULL ); + + // Construct one if we don't have one + if ( encoder == NULL ) + { + // Get the fps of the consumer (for now - should be from frame) + double fps = mlt_properties_get_double( this_properties, "fps" ); + + // Create the encoder + encoder = dv_encoder_new( fps != 25, 0, 0 ); + + // Encoder settings + encoder->isPAL = fps = 25; + encoder->is16x9 = 0; + encoder->vlc_encode_passes = 1; + encoder->static_qno = 0; + encoder->force_dct = DV_DCT_AUTO; + + // Store the encoder on the properties + mlt_properties_set_data( this_properties, "dv_encoder", encoder, 0, ( mlt_destructor )dv_encoder_free, NULL ); + + // Convenience for image dimensions + mlt_properties_set_int( this_properties, "width", 720 ); + mlt_properties_set_int( this_properties, "height", fps == 25 ? 576 : 480 ); + } + + // Return the encoder + return encoder; +} + + +/** The libdv encode video method. +*/ + +static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ) +{ + // Obtain the dv_encoder + dv_encoder_t *encoder = libdv_get_encoder( this, frame ); + + // Get the properties of the consumer + mlt_properties this_properties = mlt_consumer_properties( this ); + + // This will hold the size of the dv frame + int size = 0; + + // If we get an encoder, then encode the image + if ( encoder != NULL ) + { + // Specify desired image properties + mlt_image_format fmt = mlt_image_yuv422; + int width = mlt_properties_get_int( this_properties, "width" ); + int height = mlt_properties_get_int( this_properties, "height" ); + uint8_t *image = NULL; + + // Get the image + mlt_frame_get_image( frame, &image, &fmt, &width, &height, 0 ); + + // Check that we get what we expected + if ( fmt != mlt_image_yuv422 || + width != mlt_properties_get_int( this_properties, "width" ) || + height != mlt_properties_get_int( this_properties, "height" ) || + image == NULL ) + { + // We should try to recover here + fprintf( stderr, "We have a problem houston...\n" ); + } + else + { + // Calculate the size of the dv frame + size = height == 576 ? frame_size_625_50 : frame_size_525_60; + } + + // Process the frame + if ( size != 0 ) + { + // Encode the image + dv_encode_full_frame( encoder, &image, e_dv_color_yuv, dv_frame ); + } + } + + return size; +} + +/** The libdv encode audio method. +*/ + +static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame ) +{ + // Get the properties of the consumer + mlt_properties this_properties = mlt_consumer_properties( this ); + + // Obtain the dv_encoder + dv_encoder_t *encoder = libdv_get_encoder( this, frame ); + + // Only continue if we have an encoder + if ( encoder != NULL ) + { + // Get the frame count + int count = mlt_properties_get_int( this_properties, "count" ); + + // Default audio args + mlt_audio_format fmt = mlt_audio_pcm; + int channels = 2; + int frequency = 48000; + int samples = mlt_sample_calculator( mlt_properties_get_double( this_properties, "fps" ), frequency, count ); + int16_t *pcm = NULL; + + // Get the frame number + time_t start = time( NULL ); + int height = mlt_properties_get_int( this_properties, "height" ); + int is_pal = height == 576; + int is_wide = 0; + + // Temporary - audio buffer allocation + int16_t *audio_buffers[ 4 ]; + int i = 0; + int j = 0; + for ( i = 0 ; i < 4; i ++ ) + audio_buffers[ i ] = malloc( 2 * DV_AUDIO_MAX_SAMPLES ); + + // Get the audio + mlt_frame_get_audio( frame, &pcm, &fmt, &frequency, &channels, &samples ); + + // Inform the encoder of the number of audio samples + encoder->samples_this_frame = samples; + + // Fill the audio buffers correctly + for ( i = 0; i < samples; i ++ ) + for ( j = 0; j < channels; j++ ) + audio_buffers[ j ][ i ] = *pcm ++; + + // Encode audio on frame + dv_encode_full_audio( encoder, audio_buffers, channels, frequency, dv_frame ); + + // Specify meta data on the frame + dv_encode_metadata( dv_frame, is_pal, is_wide, &start, count ); + dv_encode_timecode( dv_frame, is_pal, count ); + + // Update properties + mlt_properties_set_int( this_properties, "count", ++ count ); + + // Temporary - free audio buffers + for ( i = 0 ; i < 4; i ++ ) + free( audio_buffers[ i ] ); + } +} + +/** The libdv output method. +*/ + +static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame ) +{ + fwrite( dv_frame, size, 1, stdout ); + fflush( stdout ); +} + +/** The main thread - the argument is simply the consumer. +*/ + +static void *consumer_thread( void *arg ) +{ + // Map the argument to the object + mlt_consumer this = arg; + + // Get the properties + mlt_properties properties = mlt_consumer_properties( this ); + + // Get the handling methods + int ( *video )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "video", NULL ); + int ( *audio )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "audio", NULL ); + int ( *output )( mlt_consumer, uint8_t *, int, mlt_frame ) = mlt_properties_get_data( properties, "output", NULL ); + + // Allocate a single PAL frame for encoding + uint8_t *dv_frame = malloc( frame_size_625_50 ); + + // Get the service associated to the consumer + mlt_service service = mlt_consumer_service( this ); + + // Define a frame pointer + mlt_frame frame; + + // Loop while running + while( mlt_properties_get_int( properties, "running" ) ) + { + // Get the frame + if ( mlt_service_get_frame( service, &frame, 0 ) == 0 ) + { + // Encode the image + int size = video( this, dv_frame, frame ); + + // Encode the audio + if ( size > 0 ) + audio( this, dv_frame, frame ); + + // Output the frame + output( this, dv_frame, size, frame ); + + // Close the frame + mlt_frame_close( frame ); + } + } + + // Tidy up + free( dv_frame ); + + return NULL; +} + +/** Close the consumer. +*/ + +static void consumer_close( mlt_consumer this ) +{ + // Get the properties + mlt_properties properties = mlt_consumer_properties( this ); + + // Get the thread + pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL ); + + // Stop the thread + mlt_properties_set_int( properties, "running", 0 ); + + // Wait for termination + pthread_join( *thread, NULL ); + + // Close the parent + mlt_consumer_close( this ); + + // Free the memory + free( this ); +} + diff --git a/src/modules/dv/consumer_libdv.h b/src/modules/dv/consumer_libdv.h new file mode 100644 index 0000000..de7311e --- /dev/null +++ b/src/modules/dv/consumer_libdv.h @@ -0,0 +1,28 @@ +/* + * producer_libdv.h -- a DV encoder based on libdv + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CONSUMER_LIBDV_H_ +#define _CONSUMER_LIBDV_H_ + +#include + +extern mlt_consumer consumer_libdv_init( char *filename ); + +#endif diff --git a/src/modules/dv/factory.c b/src/modules/dv/factory.c index e27510a..8d25f70 100644 --- a/src/modules/dv/factory.c +++ b/src/modules/dv/factory.c @@ -21,6 +21,7 @@ #include #include "producer_libdv.h" +#include "consumer_libdv.h" void *mlt_create_producer( char *id, void *arg ) { @@ -41,6 +42,8 @@ void *mlt_create_transition( char *id, void *arg ) void *mlt_create_consumer( char *id, void *arg ) { + if ( !strcmp( id, "libdv" ) ) + return consumer_libdv_init( arg ); return NULL; } diff --git a/src/modules/dv/producer_libdv.c b/src/modules/dv/producer_libdv.c index 8c139df..b82a0e6 100644 --- a/src/modules/dv/producer_libdv.c +++ b/src/modules/dv/producer_libdv.c @@ -130,11 +130,10 @@ static int producer_collect_info( producer_libdv this ) // Calculate default in/out points double fps = this->is_pal ? 25 : 30000.0 / 1001.0; - mlt_timecode length = ( mlt_timecode )( this->frames_in_file ) / fps; mlt_properties_set_double( properties, "fps", fps ); - mlt_properties_set_timecode( properties, "length", length ); - mlt_properties_set_timecode( properties, "in", 0.0 ); - mlt_properties_set_timecode( properties, "out", ( mlt_timecode )( this->frames_in_file - 1 ) / fps ); + mlt_properties_set_position( properties, "length", this->frames_in_file ); + mlt_properties_set_position( properties, "in", 0 ); + mlt_properties_set_position( properties, "out", this->frames_in_file - 1 ); // Parse the header for meta info dv_parse_header( this->dv_decoder, dv_data ); @@ -307,7 +306,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i } // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/src/modules/ffmpeg/filter_ffmpeg_dub.c b/src/modules/ffmpeg/filter_ffmpeg_dub.c index 652354b..0d678af 100644 --- a/src/modules/ffmpeg/filter_ffmpeg_dub.c +++ b/src/modules/ffmpeg/filter_ffmpeg_dub.c @@ -47,7 +47,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) ) { // Get the position - double position = mlt_properties_get_double( producer_properties, "dub_position" ); + mlt_position position = mlt_properties_get_position( producer_properties, "dub_position" ); // We need a frame from the producer mlt_frame producer_frame; @@ -56,7 +56,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format mlt_properties_set_double( producer_properties, "fps", mlt_properties_get_double( frame_properties, "fps" ) ); // Seek to the position - mlt_producer_seek_frame( producer, ( int64_t )position ); + mlt_producer_seek( producer, position ); // Get the next frame producer->get_frame( producer, &producer_frame, 0 ); @@ -70,7 +70,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format mlt_properties_set_data( frame_properties, "ffmpeg_dub_frame", producer_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); // Incrment the position - mlt_properties_set_double( producer_properties, "dub_position", position + 1 ); + mlt_properties_set_position( producer_properties, "dub_position", position + 1 ); } } @@ -135,7 +135,7 @@ mlt_filter filter_ffmpeg_dub_init( char *file ) mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL ); // Initialise the audio frame position - mlt_properties_set_double( properties, "dub_position", 0 ); + mlt_properties_set_position( properties, "dub_position", 0 ); return this; } diff --git a/src/modules/ffmpeg/producer_ffmpeg.c b/src/modules/ffmpeg/producer_ffmpeg.c index 9233bb3..f383aff 100644 --- a/src/modules/ffmpeg/producer_ffmpeg.c +++ b/src/modules/ffmpeg/producer_ffmpeg.c @@ -240,7 +240,7 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma return 0; } -FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_timecode position ) +FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_position position ) { if ( this->video == NULL ) { @@ -277,7 +277,7 @@ FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_timecode position ) return this->video; } -FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_timecode position ) +FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_position position ) { // Get the producer mlt_producer producer = &this->parent; @@ -530,12 +530,12 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i if ( this->end_of_video && this->end_of_audio ) { mlt_properties_set_int( properties, "end_of_clip", 1 ); - mlt_properties_set_timecode( producer_properties, "length", mlt_producer_position( &this->parent ) ); + mlt_properties_set_position( producer_properties, "length", mlt_producer_position( &this->parent ) ); mlt_producer_set_in_and_out( &this->parent, mlt_producer_get_in( &this->parent ), mlt_producer_position( &this->parent ) ); } // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/src/modules/gtk2/producer_pango.c b/src/modules/gtk2/producer_pango.c index 752ed4a..2a8d99f 100644 --- a/src/modules/gtk2/producer_pango.c +++ b/src/modules/gtk2/producer_pango.c @@ -340,7 +340,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i } // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Calculate the next timecode mlt_producer_prepare_next( producer ); diff --git a/src/modules/gtk2/producer_pixbuf.c b/src/modules/gtk2/producer_pixbuf.c index 84ed6e6..04a9e64 100644 --- a/src/modules/gtk2/producer_pixbuf.c +++ b/src/modules/gtk2/producer_pixbuf.c @@ -90,7 +90,7 @@ mlt_producer producer_pixbuf_init( char *filename ) gap ++; } } - mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_position( properties, "out", this->count * 25 ); } else if ( strstr( filename, "/.all." ) != NULL ) { @@ -117,7 +117,7 @@ mlt_producer producer_pixbuf_init( char *filename ) free( de[ i ] ); } - mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_position( properties, "out", this->count * 25 ); free( de ); free( dir_name ); } @@ -125,7 +125,7 @@ mlt_producer producer_pixbuf_init( char *filename ) { this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); this->filenames[ this->count ++ ] = strdup( filename ); - mlt_properties_set_timecode( properties, "out", 1 ); + mlt_properties_set_position( properties, "out", 25 ); } // Initialise gobject types @@ -207,7 +207,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count; // Update timecode on the frame we're creating - mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) ); + mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // optimization for subsequent iterations on single picture if ( this->image != NULL && image_idx == this->image_idx ) diff --git a/src/modules/inigo/producer_inigo.c b/src/modules/inigo/producer_inigo.c index 581db3d..62e02b2 100644 --- a/src/modules/inigo/producer_inigo.c +++ b/src/modules/inigo/producer_inigo.c @@ -241,10 +241,15 @@ mlt_producer producer_inigo_init( char **argv ) mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), track ); } - mlt_properties props = mlt_multitrack_properties( multitrack ); + mlt_tractor tractor = mlt_field_tractor( field ); + mlt_producer prod = mlt_tractor_producer( tractor ); + mlt_properties props = mlt_tractor_properties( tractor ); + mlt_properties_set_data( props, "multitrack", multitrack, 0, NULL, NULL ); mlt_properties_set_data( props, "field", field, 0, NULL, NULL ); mlt_properties_set_data( props, "group", group, 0, NULL, NULL ); + mlt_producer_set_in_and_out( prod, 0, mlt_producer_get_out( mlt_multitrack_producer( multitrack ) ) ); + mlt_properties_set_double( props, "fps", mlt_producer_get_fps( mlt_multitrack_producer( multitrack ) ) ); - return mlt_multitrack_producer( multitrack ); + return mlt_tractor_producer( tractor ); } diff --git a/src/modules/sdl/consumer_sdl.c b/src/modules/sdl/consumer_sdl.c index 803e96e..e56d56c 100644 --- a/src/modules/sdl/consumer_sdl.c +++ b/src/modules/sdl/consumer_sdl.c @@ -529,8 +529,7 @@ static void consumer_close( mlt_consumer parent ) pthread_mutex_destroy( &this->audio_mutex ); pthread_cond_destroy( &this->audio_cond ); - // Now clean up the rest (the close = NULL is a bit nasty but needed for now) - parent->close = NULL; + // Now clean up the rest mlt_consumer_close( parent ); // Finally clean up this -- 1.7.4.4