X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fframework%2Fmlt_producer.c;h=56d1d3f36fa8d935b03abae7341670264bb91730;hb=40b169c095486ba1b868486eb98a47c41f36ce8c;hp=b1c426993e4ff132c5c2a4bdbac0fe4e026bd102;hpb=6ab36df138729fe7eac018edf5a32cd5b9460155;p=melted diff --git a/src/framework/mlt_producer.c b/src/framework/mlt_producer.c index b1c4269..56d1d3f 100644 --- a/src/framework/mlt_producer.c +++ b/src/framework/mlt_producer.c @@ -3,19 +3,19 @@ * 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 library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" @@ -23,6 +23,8 @@ #include "mlt_factory.h" #include "mlt_frame.h" #include "mlt_parser.h" +#include "mlt_profile.h" + #include #include #include @@ -35,6 +37,13 @@ static int producer_get_frame( mlt_service this, mlt_frame_ptr frame, int index static void mlt_producer_property_changed( mlt_service owner, mlt_producer this, char *name ); static void mlt_producer_service_changed( mlt_service owner, mlt_producer this ); +//#define _MLT_PRODUCER_CHECKS_ 1 + +#ifdef _MLT_PRODUCER_CHECKS_ +static int producers_created = 0; +static int producers_destroyed = 0; +#endif + /** Constructor */ @@ -46,6 +55,10 @@ int mlt_producer_init( mlt_producer this, void *child ) // Continue if no error if ( error == 0 ) { +#ifdef _MLT_PRODUCER_CHECKS_ + producers_created ++; +#endif + // Initialise the producer memset( this, 0, sizeof( struct mlt_producer_s ) ); @@ -55,9 +68,6 @@ int mlt_producer_init( mlt_producer this, void *child ) // Initialise the service if ( mlt_service_init( &this->parent, this ) == 0 ) { - // Get the normalisation preference - char *normalisation = mlt_environment( "MLT_NORMALISATION" ); - // The parent is the service mlt_service parent = &this->parent; @@ -69,22 +79,16 @@ int mlt_producer_init( mlt_producer this, void *child ) this->close_object = this; // Get the properties of the parent - mlt_properties properties = mlt_service_properties( parent ); + mlt_properties properties = MLT_SERVICE_PROPERTIES( parent ); // Set the default properties mlt_properties_set( properties, "mlt_type", "mlt_producer" ); mlt_properties_set_position( properties, "_position", 0.0 ); mlt_properties_set_double( properties, "_frame", 0 ); - if ( normalisation == NULL || strcmp( normalisation, "NTSC" ) ) - { - mlt_properties_set_double( properties, "fps", 25.0 ); - mlt_properties_set_double( properties, "aspect_ratio", 72.0 / 79.0 ); - } - else - { - mlt_properties_set_double( properties, "fps", 30000.0 / 1001.0 ); - mlt_properties_set_double( properties, "aspect_ratio", 128.0 / 117.0 ); - } + mlt_properties_set_double( properties, "fps", mlt_profile_fps( NULL ) ); + mlt_properties_set_int( properties, "frame_rate_num", mlt_profile_get()->frame_rate_num ); + mlt_properties_set_int( properties, "frame_rate_den", mlt_profile_get()->frame_rate_den ); + mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( NULL ) ); mlt_properties_set_double( properties, "_speed", 1.0 ); mlt_properties_set_position( properties, "in", 0 ); mlt_properties_set_position( properties, "out", 14999 ); @@ -110,7 +114,7 @@ int mlt_producer_init( mlt_producer this, void *child ) static void mlt_producer_property_changed( mlt_service owner, mlt_producer this, char *name ) { if ( !strcmp( name, "in" ) || !strcmp( name, "out" ) || !strcmp( name, "length" ) ) - mlt_events_fire( mlt_producer_properties( mlt_producer_cut_parent( this ) ), "producer-changed", NULL ); + mlt_events_fire( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), "producer-changed", NULL ); } /** Listener for service changes. @@ -118,19 +122,7 @@ static void mlt_producer_property_changed( mlt_service owner, mlt_producer this, static void mlt_producer_service_changed( mlt_service owner, mlt_producer this ) { - mlt_events_fire( mlt_producer_properties( mlt_producer_cut_parent( this ) ), "producer-changed", NULL ); -} - -/** Special case destructor -*/ - -static void mlt_cut_destroy( void *obj ) -{ - mlt_producer this = obj; - this->close = NULL; - this->parent.close = NULL; - mlt_service_close( &this->parent ); - free( this ); + mlt_events_fire( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), "producer-changed", NULL ); } /** Create a new producer. @@ -140,7 +132,6 @@ mlt_producer mlt_producer_new( ) { mlt_producer this = malloc( sizeof( struct mlt_producer_s ) ); mlt_producer_init( this, NULL ); - this->close = mlt_cut_destroy; return this; } @@ -149,7 +140,7 @@ mlt_producer mlt_producer_new( ) int mlt_producer_is_cut( mlt_producer this ) { - return mlt_properties_get_int( mlt_producer_properties( this ), "_cut" ); + return mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( this ), "_cut" ); } /** Determine if producer is a mix. @@ -157,17 +148,25 @@ int mlt_producer_is_cut( mlt_producer this ) int mlt_producer_is_mix( mlt_producer this ) { - mlt_properties properties = this != NULL ? mlt_producer_properties( this ) : NULL; + mlt_properties properties = this != NULL ? MLT_PRODUCER_PROPERTIES( this ) : NULL; mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL; return tractor != NULL; } +/** Determine if the producer is a blank [from a playlist]. +*/ + +int mlt_producer_is_blank( mlt_producer this ) +{ + return this == NULL || !strcmp( mlt_properties_get( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), "resource" ), "blank" ); +} + /** Obtain the parent producer. */ mlt_producer mlt_producer_cut_parent( mlt_producer this ) { - mlt_properties properties = mlt_producer_properties( this ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); if ( mlt_producer_is_cut( this ) ) return mlt_properties_get_data( properties, "_cut_parent", NULL ); else @@ -181,21 +180,21 @@ mlt_producer mlt_producer_cut( mlt_producer this, int in, int out ) { mlt_producer result = mlt_producer_new( ); mlt_producer parent = mlt_producer_cut_parent( this ); - mlt_properties properties = mlt_producer_properties( result ); - mlt_properties parent_props = mlt_producer_properties( parent ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( result ); + mlt_properties parent_props = MLT_PRODUCER_PROPERTIES( parent ); + mlt_events_block( MLT_PRODUCER_PROPERTIES( result ), MLT_PRODUCER_PROPERTIES( result ) ); // Special case - allow for a cut of the entire producer (this will squeeze all other cuts to 0) if ( in <= 0 ) in = 0; - if ( out >= mlt_producer_get_playtime( parent ) ) - out = mlt_producer_get_playtime( parent ) - 1; + if ( ( out < 0 || out >= mlt_producer_get_length( parent ) ) && !mlt_producer_is_blank( this ) ) + out = mlt_producer_get_length( parent ) - 1; mlt_properties_inc_ref( parent_props ); mlt_properties_set_int( properties, "_cut", 1 ); mlt_properties_set_data( properties, "_cut_parent", parent, 0, ( mlt_destructor )mlt_producer_close, NULL ); mlt_properties_set_position( properties, "length", mlt_properties_get_position( parent_props, "length" ) ); - mlt_properties_set_position( properties, "in", 0 ); - mlt_properties_set_position( properties, "out", 0 ); + mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( parent_props, "aspect_ratio" ) ); mlt_producer_set_in_and_out( result, in, out ); return result; @@ -214,7 +213,7 @@ mlt_service mlt_producer_service( mlt_producer this ) mlt_properties mlt_producer_properties( mlt_producer this ) { - return mlt_service_properties( &this->parent ); + return MLT_SERVICE_PROPERTIES( &this->parent ); } /** Seek to a specified position. @@ -223,34 +222,35 @@ mlt_properties mlt_producer_properties( mlt_producer this ) int mlt_producer_seek( mlt_producer this, mlt_position position ) { // Determine eof handling - mlt_properties properties = mlt_producer_properties( this ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); char *eof = mlt_properties_get( properties, "eof" ); int use_points = 1 - mlt_properties_get_int( properties, "ignore_points" ); - // Recursive behaviour for cuts... + // Recursive behaviour for cuts - repositions parent and then repositions cut + // hence no return on this condition if ( mlt_producer_is_cut( this ) ) mlt_producer_seek( mlt_producer_cut_parent( this ), position + mlt_producer_get_in( this ) ); // Check bounds - if ( position < 0 ) + if ( position < 0 || mlt_producer_get_playtime( this ) == 0 ) { position = 0; } - else if ( use_points && !strcmp( eof, "pause" ) && position >= mlt_producer_get_playtime( this ) ) + else if ( use_points && ( eof == NULL || !strcmp( eof, "pause" ) ) && position >= mlt_producer_get_playtime( this ) ) { mlt_producer_set_speed( this, 0 ); position = mlt_producer_get_playtime( this ) - 1; } else if ( use_points && !strcmp( eof, "loop" ) && position >= mlt_producer_get_playtime( this ) ) { - position = position % mlt_producer_get_playtime( this ); + position = (int)position % (int)mlt_producer_get_playtime( this ); } // Set the position - mlt_properties_set_position( mlt_producer_properties( this ), "_position", position ); + mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( this ), "_position", position ); // Calculate the absolute frame - mlt_properties_set_position( mlt_producer_properties( this ), "_frame", use_points * mlt_producer_get_in( this ) + position ); + mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( this ), "_frame", use_points * mlt_producer_get_in( this ) + position ); return 0; } @@ -260,7 +260,7 @@ int mlt_producer_seek( mlt_producer this, mlt_position position ) mlt_position mlt_producer_position( mlt_producer this ) { - return mlt_properties_get_position( mlt_producer_properties( this ), "_position" ); + return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "_position" ); } /** Get the current position (relative to start of producer). @@ -268,7 +268,7 @@ mlt_position mlt_producer_position( mlt_producer this ) mlt_position mlt_producer_frame( mlt_producer this ) { - return mlt_properties_get_position( mlt_producer_properties( this ), "_frame" ); + return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "_frame" ); } /** Set the playing speed. @@ -276,7 +276,7 @@ mlt_position mlt_producer_frame( mlt_producer this ) int mlt_producer_set_speed( mlt_producer this, double speed ) { - return mlt_properties_set_double( mlt_producer_properties( this ), "_speed", speed ); + return mlt_properties_set_double( MLT_PRODUCER_PROPERTIES( this ), "_speed", speed ); } /** Get the playing speed. @@ -284,7 +284,7 @@ int mlt_producer_set_speed( mlt_producer this, double speed ) double mlt_producer_get_speed( mlt_producer this ) { - return mlt_properties_get_double( mlt_producer_properties( this ), "_speed" ); + return mlt_properties_get_double( MLT_PRODUCER_PROPERTIES( this ), "_speed" ); } /** Get the frames per second. @@ -292,7 +292,7 @@ double mlt_producer_get_speed( mlt_producer this ) double mlt_producer_get_fps( mlt_producer this ) { - return mlt_properties_get_double( mlt_producer_properties( this ), "fps" ); + return mlt_properties_get_double( MLT_PRODUCER_PROPERTIES( this ), "fps" ); } /** Set the in and out points. @@ -300,18 +300,20 @@ double mlt_producer_get_fps( mlt_producer this ) int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out ) { - mlt_properties properties = mlt_producer_properties( this ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); // Correct ins and outs if necessary if ( in < 0 ) in = 0; - else if ( in > mlt_producer_get_length( this ) ) - in = mlt_producer_get_length( this ); + else if ( in >= mlt_producer_get_length( this ) ) + in = mlt_producer_get_length( this ) - 1; if ( out < 0 ) out = 0; - else if ( out > mlt_producer_get_length( this ) ) - out = mlt_producer_get_length( this ); + else if ( out >= mlt_producer_get_length( this ) && !mlt_producer_is_blank( this ) ) + out = mlt_producer_get_length( this ) - 1; + else if ( out >= mlt_producer_get_length( this ) && mlt_producer_is_blank( this ) ) + mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( this ), "length", out + 1 ); // Swap ins and outs if wrong if ( out < in ) @@ -338,7 +340,7 @@ int mlt_producer_clear( mlt_producer this ) { if ( this != NULL ) { - mlt_properties properties = mlt_producer_properties( this ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); mlt_events_block( properties, properties ); mlt_properties_set_position( properties, "in", 0 ); mlt_events_unblock( properties, properties ); @@ -352,7 +354,7 @@ int mlt_producer_clear( mlt_producer this ) mlt_position mlt_producer_get_in( mlt_producer this ) { - return mlt_properties_get_position( mlt_producer_properties( this ), "in" ); + return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "in" ); } /** Get the out point. @@ -360,7 +362,7 @@ mlt_position mlt_producer_get_in( mlt_producer this ) mlt_position mlt_producer_get_out( mlt_producer this ) { - return mlt_properties_get_position( mlt_producer_properties( this ), "out" ); + return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "out" ); } /** Get the total play time. @@ -376,7 +378,7 @@ mlt_position mlt_producer_get_playtime( mlt_producer this ) mlt_position mlt_producer_get_length( mlt_producer this ) { - return mlt_properties_get_position( mlt_producer_properties( this ), "length" ); + return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "length" ); } /** Prepare for next frame. @@ -384,7 +386,8 @@ mlt_position mlt_producer_get_length( mlt_producer this ) void mlt_producer_prepare_next( mlt_producer this ) { - mlt_producer_seek( this, mlt_producer_position( this ) + mlt_producer_get_speed( this ) ); + if ( mlt_producer_get_speed( this ) != 0 ) + mlt_producer_seek( this, mlt_producer_position( this ) + mlt_producer_get_speed( this ) ); } /** Get a frame. @@ -393,15 +396,15 @@ void mlt_producer_prepare_next( mlt_producer this ) static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int index ) { int result = 1; - mlt_producer this = service->child; + mlt_producer this = service != NULL ? service->child : NULL; - if ( !mlt_producer_is_cut( this ) ) + if ( this != NULL && !mlt_producer_is_cut( this ) ) { // Get the properties of this producer - mlt_properties properties = mlt_producer_properties( this ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); // Determine eof handling - char *eof = mlt_properties_get( mlt_producer_properties( this ), "eof" ); + char *eof = mlt_properties_get( MLT_PRODUCER_PROPERTIES( this ), "eof" ); // Get the speed of the producer double speed = mlt_producer_get_speed( this ); @@ -422,8 +425,8 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind result = mlt_frame_set_position( *frame, mlt_producer_position( this ) ); // Mark as a test card - mlt_properties_set_int( mlt_frame_properties( *frame ), "test_image", 1 ); - mlt_properties_set_int( mlt_frame_properties( *frame ), "test_audio", 1 ); + mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", 1 ); + mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_audio", 1 ); // Calculate the next position mlt_producer_prepare_next( this ); @@ -435,7 +438,7 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind } // Copy the fps and speed of the producer onto the frame - properties = mlt_frame_properties( *frame ); + properties = MLT_FRAME_PROPERTIES( *frame ); mlt_properties_set_double( properties, "_speed", speed ); mlt_properties_set_double( properties, "fps", mlt_producer_get_fps( this ) ); mlt_properties_set_int( properties, "test_audio", mlt_frame_is_test_audio( *frame ) ); @@ -443,16 +446,19 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind if ( mlt_properties_get_data( properties, "_producer", NULL ) == NULL ) mlt_properties_set_data( properties, "_producer", service, 0, NULL, NULL ); } - else + else if ( this != NULL ) { + // Get the speed of the cut + double speed = mlt_producer_get_speed( this ); + // Get the parent of this cut mlt_producer parent = mlt_producer_cut_parent( this ); // Get the properties of the parent - mlt_properties parent_properties = mlt_producer_properties( parent ); + mlt_properties parent_properties = MLT_PRODUCER_PROPERTIES( parent ); // Get the properties of the cut - mlt_properties properties = mlt_producer_properties( this ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); // Determine the clone index int clone_index = mlt_properties_get_int( properties, "_clone" ); @@ -464,7 +470,7 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind { char key[ 25 ]; sprintf( key, "_clone.%d", clone_index - 1 ); - clone = mlt_properties_get_data( mlt_producer_properties( mlt_producer_cut_parent( this ) ), key, NULL ); + clone = mlt_properties_get_data( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), key, NULL ); if ( clone == NULL ) fprintf( stderr, "requested clone doesn't exist %d\n", clone_index ); clone = clone == NULL ? this : clone; } @@ -480,10 +486,39 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind mlt_properties_set_data( parent_properties, "use_clone", clone, 0, NULL, NULL ); // Now get the frame from the parents service - result = mlt_service_get_frame( mlt_producer_service( parent ), frame, index ); + result = mlt_service_get_frame( MLT_PRODUCER_SERVICE( parent ), frame, index ); // We're done with the clone now mlt_properties_set_data( parent_properties, "use_clone", NULL, 0, NULL, NULL ); + + // This is useful and required by always_active transitions to determine in/out points of the cut + if ( mlt_properties_get_data( MLT_FRAME_PROPERTIES( *frame ), "_producer", NULL ) == MLT_PRODUCER_SERVICE( parent ) ) + mlt_properties_set_data( MLT_FRAME_PROPERTIES( *frame ), "_producer", this, 0, NULL, NULL ); + + mlt_properties_set_double( MLT_FRAME_PROPERTIES( *frame ), "_speed", speed ); + mlt_producer_prepare_next( this ); + } + else + { + *frame = mlt_frame_init( ); + result = 0; + } + + // Pass on all meta properties from the producer/cut on to the frame + if ( *frame != NULL && this != NULL ) + { + int i = 0; + mlt_properties p_props = MLT_PRODUCER_PROPERTIES( this ); + mlt_properties f_props = MLT_FRAME_PROPERTIES( *frame ); + int count = mlt_properties_count( p_props ); + for ( i = 0; i < count; i ++ ) + { + char *name = mlt_properties_get_name( p_props, i ); + if ( !strncmp( name, "meta.", 5 ) ) + mlt_properties_set( f_props, name, mlt_properties_get( p_props, name ) ); + else if ( !strncmp( name, "set.", 4 ) ) + mlt_properties_set( f_props, name + 4, mlt_properties_get( p_props, name ) ); + } } return result; @@ -494,7 +529,7 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind int mlt_producer_attach( mlt_producer this, mlt_filter filter ) { - return mlt_service_attach( mlt_producer_service( this ), filter ); + return mlt_service_attach( MLT_PRODUCER_SERVICE( this ), filter ); } /** Detach a filter. @@ -502,7 +537,7 @@ int mlt_producer_attach( mlt_producer this, mlt_filter filter ) int mlt_producer_detach( mlt_producer this, mlt_filter filter ) { - return mlt_service_detach( mlt_producer_service( this ), filter ); + return mlt_service_detach( MLT_PRODUCER_SERVICE( this ), filter ); } /** Retrieve a filter. @@ -510,7 +545,7 @@ int mlt_producer_detach( mlt_producer this, mlt_filter filter ) mlt_filter mlt_producer_filter( mlt_producer this, int index ) { - return mlt_service_filter( mlt_producer_service( this ), index ); + return mlt_service_filter( MLT_PRODUCER_SERVICE( this ), index ); } /** Clone this producer. @@ -519,10 +554,12 @@ mlt_filter mlt_producer_filter( mlt_producer this, int index ) static mlt_producer mlt_producer_clone( mlt_producer this ) { mlt_producer clone = NULL; - mlt_properties properties = mlt_producer_properties( this ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); char *resource = mlt_properties_get( properties, "resource" ); char *service = mlt_properties_get( properties, "mlt_service" ); + mlt_events_block( mlt_factory_event_object( ), mlt_factory_event_object( ) ); + if ( service != NULL ) clone = mlt_factory_producer( service, resource ); @@ -530,7 +567,9 @@ static mlt_producer mlt_producer_clone( mlt_producer this ) clone = mlt_factory_producer( "fezzik", resource ); if ( clone != NULL ) - mlt_properties_inherit( mlt_producer_properties( clone ), properties ); + mlt_properties_inherit( MLT_PRODUCER_PROPERTIES( clone ), properties ); + + mlt_events_unblock( mlt_factory_event_object( ), mlt_factory_event_object( ) ); return clone; } @@ -541,7 +580,7 @@ static mlt_producer mlt_producer_clone( mlt_producer this ) static void mlt_producer_set_clones( mlt_producer this, int clones ) { mlt_producer parent = mlt_producer_cut_parent( this ); - mlt_properties properties = mlt_producer_properties( parent ); + mlt_properties properties = MLT_PRODUCER_PROPERTIES( parent ); int existing = mlt_properties_get_int( properties, "_clones" ); int i = 0; char key[ 25 ]; @@ -575,7 +614,7 @@ static void mlt_producer_set_clones( mlt_producer this, int clones ) sprintf( key, "_clone.%d", i ); clone = mlt_properties_get_data( properties, key, NULL ); if ( clone != NULL ) - mlt_properties_pass( mlt_producer_properties( clone ), properties, "" ); + mlt_properties_pass( MLT_PRODUCER_PROPERTIES( clone ), properties, "" ); } // Update the number of clones on the properties @@ -670,7 +709,7 @@ static int on_start_producer( mlt_parser this, mlt_producer object ) refs = malloc( ( ref_count + 1 ) * sizeof( clip_references ) ); if ( old_refs != NULL ) memcpy( refs, old_refs, ref_count * sizeof( clip_references ) ); - mlt_properties_set_int( mlt_producer_properties( object ), "_clone", -1 ); + mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( object ), "_clone", -1 ); refs[ ref_count ].cut = object; refs[ ref_count ].start = info->position; refs[ ref_count ].end = info->position + mlt_producer_get_playtime( object ) - 1; @@ -720,7 +759,7 @@ int mlt_producer_optimise( mlt_producer this ) parser->on_start_multitrack = on_start_multitrack; parser->on_end_multitrack = on_end_multitrack; push( parser, 0, 0, 0 ); - mlt_parser_start( parser, mlt_producer_service( this ) ); + mlt_parser_start( parser, MLT_PRODUCER_SERVICE( this ) ); free( pop( parser ) ); for ( k = 0; k < mlt_properties_count( producers ); k ++ ) { @@ -740,7 +779,7 @@ int mlt_producer_optimise( mlt_producer this ) if ( intersect( &refs[ i ], &refs[ j ] ) ) { clones ++; - mlt_properties_set_int( mlt_producer_properties( refs[ j ].cut ), "_clone", clones ); + mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( refs[ j ].cut ), "_clone", clones ); } } if ( clones > max_clones ) @@ -750,8 +789,8 @@ int mlt_producer_optimise( mlt_producer this ) for ( i = 0; i < count; i ++ ) { mlt_producer cut = refs[ i ].cut; - if ( mlt_properties_get_int( mlt_producer_properties( cut ), "_clone" ) == -1 ) - mlt_properties_set_int( mlt_producer_properties( cut ), "_clone", 0 ); + if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone" ) == -1 ) + mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone", 0 ); } mlt_producer_set_clones( producer, max_clones ); @@ -762,7 +801,7 @@ int mlt_producer_optimise( mlt_producer this ) for ( i = 0; i < count; i ++ ) { mlt_producer cut = refs[ i ].cut; - mlt_properties_set_int( mlt_producer_properties( cut ), "_clone", 0 ); + mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone", 0 ); } mlt_producer_set_clones( producer, 0 ); } @@ -777,13 +816,35 @@ int mlt_producer_optimise( mlt_producer this ) void mlt_producer_close( mlt_producer this ) { - if ( this != NULL && mlt_properties_dec_ref( mlt_producer_properties( this ) ) <= 0 ) + if ( this != NULL && mlt_properties_dec_ref( MLT_PRODUCER_PROPERTIES( this ) ) <= 0 ) { this->parent.close = NULL; if ( this->close != NULL ) + { this->close( this->close_object ); + } else + { + int destroy = mlt_producer_is_cut( this ); + +#if _MLT_PRODUCER_CHECKS_ == 1 + // Show debug info + mlt_properties_debug( MLT_PRODUCER_PROPERTIES( this ), "Producer closing", stderr ); +#endif + +#ifdef _MLT_PRODUCER_CHECKS_ + // Increment destroyed count + producers_destroyed ++; + + // Show current stats - these should match when the app is closed + fprintf( stderr, "Producers created %d, destroyed %d\n", producers_created, producers_destroyed ); +#endif + mlt_service_close( &this->parent ); + + if ( destroy ) + free( this ); + } } }