]> git.sesse.net Git - mlt/commitdiff
Cut management part 1
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Fri, 24 Sep 2004 13:30:03 +0000 (13:30 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Fri, 24 Sep 2004 13:30:03 +0000 (13:30 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@441 d19143bc-622f-0410-bfdd-b5b2a6649095

src/framework/mlt_playlist.c
src/framework/mlt_producer.c
src/framework/mlt_producer.h
src/framework/mlt_properties.c
src/framework/mlt_service.c
src/modules/westley/consumer_westley.c
src/modules/westley/producer_westley.c

index c9a9d1ba1b65a3fe62e19c8f29b62042df1f26f3..579aeb1dd7fe06b33cdc54301c77316881a591f1 100644 (file)
@@ -215,10 +215,19 @@ static void mlt_playlist_listener( mlt_producer producer, mlt_playlist this )
 /** Append to the virtual playlist.
 */
 
-static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out )
+static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer source, mlt_position in, mlt_position out )
 {
+       mlt_producer producer = mlt_producer_is_cut( source ) ? source : mlt_producer_cut( source, in, out );
        mlt_properties properties = mlt_producer_properties( producer );
 
+       // If we have a cut, then use the in/out points from the cut
+       if ( mlt_producer_is_cut( source ) )
+       {
+               mlt_properties_inc_ref( properties );
+               in = mlt_producer_get_in( source );
+               out = mlt_producer_get_out( source );
+       }
+
        // Check that we have room
        if ( this->count >= this->size )
        {
@@ -243,7 +252,6 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer
 
        this->count ++;
 
-       mlt_properties_inc_ref( properties );
 
        return mlt_playlist_virtual_refresh( this );
 }
@@ -296,7 +304,6 @@ static mlt_service mlt_playlist_virtual_seek( mlt_playlist this )
        // Seek in real producer to relative position
        if ( producer != NULL )
        {
-               position += this->list[ i ]->frame_in;
                mlt_producer_seek( producer, position );
        }
        else if ( !strcmp( eof, "pause" ) && total > 0 )
@@ -315,7 +322,7 @@ static mlt_service mlt_playlist_virtual_seek( mlt_playlist this )
                mlt_producer this_producer = mlt_playlist_producer( this );
                mlt_producer_seek( this_producer, 0 );
                producer = entry->producer;
-               mlt_producer_seek( producer, entry->frame_in );
+               mlt_producer_seek( producer, 0 );
        }
        else
        {
index 79038fb9015ad9e2dd721ffa054c28b0901fe2ad..843a2451a9286d90046d1813a2cb5debab539b6d 100644 (file)
@@ -130,6 +130,53 @@ mlt_producer mlt_producer_new( )
        return this;
 }
 
+/** Determine if producer is a cut.
+*/
+
+int mlt_producer_is_cut( mlt_producer this )
+{
+       return mlt_properties_get_int( mlt_producer_properties( this ), "_cut" );
+}
+
+/** Obtain the parent producer.
+*/
+
+mlt_producer mlt_producer_cut_parent( mlt_producer this )
+{
+       mlt_properties properties = mlt_producer_properties( this );
+       if ( mlt_producer_is_cut( this ) )
+               return mlt_properties_get_data( properties, "_cut_parent", NULL );
+       else
+               return this;
+}
+
+/** Create a cut of this producer
+*/
+
+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 );
+
+       // 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;
+
+       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_producer_set_in_and_out( result, in, out );
+
+       return result;
+}
+
 /** Get the parent service object.
 */
 
@@ -152,8 +199,13 @@ mlt_properties mlt_producer_properties( mlt_producer this )
 int mlt_producer_seek( mlt_producer this, mlt_position position )
 {
        // Determine eof handling
-       char *eof = mlt_properties_get( mlt_producer_properties( this ), "eof" );
-       int use_points = 1 - mlt_properties_get_int( mlt_producer_properties( this ), "ignore_points" );
+       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...
+       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 )
@@ -303,40 +355,52 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind
        int result = 1;
        mlt_producer this = service->child;
 
-       // Determine eof handling
-       char *eof = mlt_properties_get( mlt_producer_properties( this ), "eof" );
-
-       // A properly instatiated producer will have a get_frame method...
-       if ( this->get_frame == NULL || ( !strcmp( eof, "continue" ) && mlt_producer_position( this ) > mlt_producer_get_out( this ) ) )
+       if ( !mlt_producer_is_cut( this ) )
        {
-               // Generate a test frame
-               *frame = mlt_frame_init( );
+               // Determine eof handling
+               char *eof = mlt_properties_get( mlt_producer_properties( this ), "eof" );
+
+               // A properly instatiated producer will have a get_frame method...
+               if ( this->get_frame == NULL || ( !strcmp( eof, "continue" ) && mlt_producer_position( this ) > mlt_producer_get_out( this ) ) )
+               {
+                       // Generate a test frame
+                       *frame = mlt_frame_init( );
 
-               // Set the position
-               result = mlt_frame_set_position( *frame, mlt_producer_position( this ) );
+                       // Set the position
+                       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 );
+                       // 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 );
 
-               // Calculate the next position
-               mlt_producer_prepare_next( this );
+                       // Calculate the next position
+                       mlt_producer_prepare_next( this );
+               }
+               else
+               {
+                       // Get the frame from the implementation
+                       result = this->get_frame( this, frame, index );
+               }
+
+               // Copy the fps and speed of the producer onto the frame
+               mlt_properties properties = mlt_frame_properties( *frame );
+               double speed = mlt_producer_get_speed( this );
+               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 ) );
+               mlt_properties_set_int( properties, "test_image", mlt_frame_is_test_card( *frame ) );
        }
        else
        {
-               // Get the frame from the implementation
-               result = this->get_frame( this, frame, index );
+               mlt_properties properties = mlt_producer_properties( this );
+               mlt_producer_seek( this, mlt_properties_get_int( properties, "_position" ) );
+               result = producer_get_frame( mlt_producer_service( mlt_producer_cut_parent( this ) ), frame, index );
+               double speed = mlt_producer_get_speed( this );
+               mlt_properties_set_double( mlt_frame_properties( *frame ), "_speed", speed );
+               mlt_producer_prepare_next( this );
        }
 
-       // 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 );
-       mlt_properties_set_int( properties, "test_audio", mlt_frame_is_test_audio( *frame ) );
-       mlt_properties_set_int( properties, "test_image", mlt_frame_is_test_card( *frame ) );
-
-       return 0;
+       return result;
 }
 
 /** Attach a filter.
index aabd557227c8d14773155e7f3837ec6a3334b63e..fb2059fb8e862a591a4023820712c8f4b8df35eb 100644 (file)
@@ -64,6 +64,9 @@ extern void mlt_producer_prepare_next( mlt_producer self );
 extern int mlt_producer_attach( mlt_producer self, mlt_filter filter );
 extern int mlt_producer_detach( mlt_producer self, mlt_filter filter );
 extern mlt_filter mlt_producer_filter( mlt_producer self, int index );
+extern mlt_producer mlt_producer_cut( mlt_producer self, int in, int out );
+extern int mlt_producer_is_cut( mlt_producer self );
+extern mlt_producer mlt_producer_cut_parent( mlt_producer self );
 extern void mlt_producer_close( mlt_producer self );
 
 #endif
index 1d13714634b051a3e815981dd76650378de08452..972ad939efa237cc49248e6950921f236a79f9ab 100644 (file)
@@ -47,7 +47,7 @@ property_list;
 /** Memory leak checks.
 */
 
-//#define _MLT_PROPERTY_CHECKS_
+#define _MLT_PROPERTY_CHECKS_
 
 #ifdef _MLT_PROPERTY_CHECKS_
 static int properties_created = 0;
index e91e441523d70d550db1c26779f2ae349967461a..9a0cd7722f8041a3cc583efa8b07b159cf772e27 100644 (file)
@@ -271,6 +271,10 @@ void mlt_service_apply_filters( mlt_service this, mlt_frame frame, int index )
        mlt_service_base *base = this->local;
        mlt_position position = mlt_properties_get_position( frame_properties, "_position" );
 
+       // Hmm - special case for cuts - apply filters from the parent first
+       if ( mlt_properties_get_int( filter_properties, "_cut" ) )
+               mlt_service_apply_filters( ( mlt_service )mlt_properties_get_data( filter_properties, "_cut_parent", NULL ), frame, 0 );
+
        if ( index == 0 || mlt_properties_get_int( filter_properties, "_filter_private" ) == 0 )
        {
                // Process the frame with the attached filters
index 35afa6ee9e09e170723f0d8d0ed1537276dc9df7..fe8d3758af228d9ff10f50583a03325699f14beb 100644 (file)
@@ -323,19 +323,20 @@ static void serialise_playlist( serialise_context context, mlt_service service,
                        {
                                if ( info.producer != NULL )
                                {
-                                       char *service_s = mlt_properties_get( mlt_producer_properties( info.producer ), "mlt_service" );
-                                       char *resource_s = mlt_properties_get( mlt_producer_properties( info.producer ), "resource" );
+                                       mlt_producer producer = mlt_producer_cut_parent( info.producer );
+                                       char *service_s = mlt_properties_get( mlt_producer_properties( producer ), "mlt_service" );
+                                       char *resource_s = mlt_properties_get( mlt_producer_properties( producer ), "resource" );
                                        if ( resource_s != NULL && !strcmp( resource_s, "<tractor>" ) )
                                        {
-                                               serialise_tractor( context, MLT_SERVICE( info.producer ), node );
+                                               serialise_tractor( context, MLT_SERVICE( producer ), node );
                                                context->pass ++;
-                                               serialise_tractor( context, MLT_SERVICE( info.producer ), node );
+                                               serialise_tractor( context, MLT_SERVICE( producer ), node );
                                                context->pass --;
                                        }
                                        else if ( service_s != NULL && strcmp( service_s, "blank" ) != 0 )
-                                               serialise_service( context, MLT_SERVICE( info.producer ), node );
+                                               serialise_service( context, MLT_SERVICE( producer ), node );
                                        else if ( resource_s != NULL && !strcmp( resource_s, "<playlist>" ) )
-                                               serialise_playlist( context, MLT_SERVICE( info.producer ), node );
+                                               serialise_playlist( context, MLT_SERVICE( producer ), node );
                                }
                        }
                }
@@ -353,7 +354,8 @@ static void serialise_playlist( serialise_context context, mlt_service service,
                {
                        if ( ! mlt_playlist_get_clip_info( MLT_PLAYLIST( service ), &info, i ) )
                        {
-                               char *service_s = mlt_properties_get( mlt_producer_properties( info.producer ), "mlt_service" );
+                               mlt_producer producer = mlt_producer_cut_parent( info.producer );
+                               char *service_s = mlt_properties_get( mlt_producer_properties( producer ), "mlt_service" );
                                if ( service_s != NULL && strcmp( service_s, "blank" ) == 0 )
                                {
                                        char length[ 20 ];
@@ -366,12 +368,14 @@ static void serialise_playlist( serialise_context context, mlt_service service,
                                {
                                        char temp[ 20 ];
                                        xmlNode *entry = xmlNewChild( child, NULL, "entry", NULL );
-                                       id = westley_get_id( context, MLT_SERVICE( info.producer ), westley_existing );
+                                       id = westley_get_id( context, MLT_SERVICE( producer ), westley_existing );
                                        xmlNewProp( entry, "producer", id );
                                        sprintf( temp, "%d", info.frame_in );
                                        xmlNewProp( entry, "in", temp );
                                        sprintf( temp, "%d", info.frame_out );
                                        xmlNewProp( entry, "out", temp );
+                                       if ( mlt_producer_is_cut( info.producer ) )
+                                               serialise_service_filters( context, mlt_producer_service( info.producer ), entry );
                                }
                        }
                }
index 46fd80965a476b1181cf397a465582e8419607af..4e5bad86a77c868dc118355890aab53e2d5ec1c6 100644 (file)
@@ -599,7 +599,76 @@ static void on_start_blank( deserialise_context context, const xmlChar *name, co
        }
 }
 
-static void on_start_entry_track( deserialise_context context, const xmlChar *name, const xmlChar **atts)
+static void on_start_entry( deserialise_context context, const xmlChar *name, const xmlChar **atts)
+{
+       mlt_producer entry = NULL;
+       mlt_properties temp = mlt_properties_new( );
+
+       for ( ; atts != NULL && *atts != NULL; atts += 2 )
+       {
+               mlt_properties_set( temp, (char*) atts[0], (char*) atts[1] );
+               
+               // Look for the producer attribute
+               if ( strcmp( atts[ 0 ], "producer" ) == 0 )
+               {
+                       mlt_producer producer = mlt_properties_get_data( context->producer_map, (char*) atts[1], NULL );
+                       if ( producer !=  NULL )
+                               mlt_properties_set_data( temp, "producer", producer, 0, NULL, NULL );
+               }
+       }
+
+       // If we have a valid entry
+       if ( mlt_properties_get_data( temp, "producer", NULL ) != NULL )
+       {
+               mlt_playlist_clip_info info;
+               enum service_type parent_type;
+               mlt_service parent = context_pop_service( context, &parent_type );
+               mlt_producer producer = mlt_properties_get_data( temp, "producer", NULL );
+
+               if ( parent_type == mlt_playlist_type )
+               {
+                       // Append the producer to the playlist
+                       if ( mlt_properties_get( temp, "in" ) != NULL || mlt_properties_get( temp, "out" ) != NULL )
+                       {
+                               mlt_playlist_append_io( MLT_PLAYLIST( parent ), producer,
+                                       mlt_properties_get_position( temp, "in" ), 
+                                       mlt_properties_get_position( temp, "out" ) );
+                       }
+                       else
+                       {
+                               mlt_playlist_append( MLT_PLAYLIST( parent ), producer );
+                       }
+
+                       mlt_playlist_get_clip_info( MLT_PLAYLIST( parent ), &info, mlt_playlist_count( MLT_PLAYLIST( parent ) ) - 1 );
+                       entry = info.producer;
+               }
+               else
+               {
+                       fprintf( stderr, "Entry not part of a playlist...\n" );
+               }
+
+               context_push_service( context, parent, parent_type );
+       }
+
+       // Push the cut onto the stack
+       context_push_service( context, mlt_producer_service( entry ), mlt_entry_type );
+
+       mlt_properties_close( temp );
+}
+
+static void on_end_entry( deserialise_context context, const xmlChar *name )
+{
+       // Get the entry from the stack
+       enum service_type entry_type;
+       mlt_service entry = context_pop_service( context, &entry_type );
+
+       if ( entry == NULL && entry_type != mlt_entry_type )
+       {
+               fprintf( stderr, "Invalid state at end of entry\n" );
+       }
+}
+
+static void on_start_track( deserialise_context context, const xmlChar *name, const xmlChar **atts)
 {
        // use a dummy service to hold properties to allow arbitrary nesting
        mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
@@ -608,10 +677,7 @@ static void on_start_entry_track( deserialise_context context, const xmlChar *na
        // Push the dummy service onto the stack
        context_push_service( context, service, mlt_entry_type );
        
-       if ( strcmp( name, "entry" ) == 0 )
-               mlt_properties_set( mlt_service_properties( service ), "resource", "<entry>" );
-       else
-               mlt_properties_set( mlt_service_properties( service ), "resource", "<track>" );
+       mlt_properties_set( mlt_service_properties( service ), "resource", "<track>" );
        
        for ( ; atts != NULL && *atts != NULL; atts += 2 )
        {
@@ -688,50 +754,6 @@ static void on_end_track( deserialise_context context, const xmlChar *name )
        }
 }
 
-static void on_end_entry( deserialise_context context, const xmlChar *name )
-{
-       // Get the entry from the stack
-       enum service_type entry_type;
-       mlt_service entry = context_pop_service( context, &entry_type );
-
-       if ( entry != NULL && entry_type == mlt_entry_type )
-       {
-               mlt_properties entry_props = mlt_service_properties( entry );
-               enum service_type parent_type;
-               mlt_service parent = context_pop_service( context, &parent_type );
-               mlt_producer producer = mlt_properties_get_data( entry_props, "producer", NULL );
-
-               if ( parent_type == mlt_playlist_type )
-               {
-                       // Append the producer to the playlist
-                       if ( mlt_properties_get( mlt_service_properties( entry ), "in" ) != NULL ||
-                               mlt_properties_get( mlt_service_properties( entry ), "out" ) != NULL )
-                       {
-                               mlt_playlist_append_io( MLT_PLAYLIST( parent ), producer,
-                                       mlt_properties_get_position( mlt_service_properties( entry ), "in" ), 
-                                       mlt_properties_get_position( mlt_service_properties( entry ), "out" ) );
-                       }
-                       else
-                       {
-                               mlt_playlist_append( MLT_PLAYLIST( parent ), producer );
-                       }
-               }
-               else
-               {
-                       fprintf( stderr, "Invalid position for an entry...\n" );
-               }
-
-               if ( parent != NULL )
-                       context_push_service( context, parent, parent_type );
-
-               mlt_service_close( entry );
-       }
-       else
-       {
-               fprintf( stderr, "Invalid state at end of entry\n" );
-       }
-}
-
 static void on_start_filter( deserialise_context context, const xmlChar *name, const xmlChar **atts)
 {
        // use a dummy service to hold properties to allow arbitrary nesting
@@ -994,8 +1016,10 @@ static void on_start_element( void *ctx, const xmlChar *name, const xmlChar **at
                on_start_producer( context, name, atts );
        else if ( strcmp( name, "blank" ) == 0 )
                on_start_blank( context, name, atts );
-       else if ( strcmp( name, "entry" ) == 0 || strcmp( name, "track" ) == 0 )
-               on_start_entry_track( context, name, atts );
+       else if ( strcmp( name, "entry" ) == 0 )
+               on_start_entry( context, name, atts );
+       else if ( strcmp( name, "track" ) == 0 )
+               on_start_track( context, name, atts );
        else if ( strcmp( name, "filter" ) == 0 )
                on_start_filter( context, name, atts );
        else if ( strcmp( name, "transition" ) == 0 )