]> git.sesse.net Git - mlt/blobdiff - src/framework/mlt_transition.c
Mlt Ref Counts and Playlist split/join
[mlt] / src / framework / mlt_transition.c
index de416a8177b9cc67d4aff8bbf521b47da7a69825..13957752d2c39a5a1c428e0be31fa94f76c4b5fc 100644 (file)
@@ -45,9 +45,11 @@ int mlt_transition_init( mlt_transition this, void *child )
                mlt_properties properties = mlt_transition_properties( this );
 
                service->get_frame = transition_get_frame;
+               service->close = ( mlt_destructor )mlt_transition_close;
+               service->close_object = this;
 
-               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 );
 
@@ -56,12 +58,23 @@ int mlt_transition_init( mlt_transition this, void *child )
        return 1;
 }
 
+/** Create a new transition.
+*/
+
+mlt_transition mlt_transition_new( )
+{
+       mlt_transition this = calloc( 1, sizeof( struct mlt_transition_s ) );
+       if ( this != NULL )
+               mlt_transition_init( this, NULL );
+       return this;
+}
+
 /** Get the service associated to the transition.
 */
 
 mlt_service mlt_transition_service( mlt_transition this )
 {
-       return &this->parent;
+       return this != NULL ? &this->parent : NULL;
 }
 
 /** Get the properties interface.
@@ -91,11 +104,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.
@@ -103,8 +116,7 @@ void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_ti
 
 int mlt_transition_get_a_track( mlt_transition this )
 {
-       mlt_properties properties = mlt_transition_properties( this );
-       return mlt_properties_get_int( properties, "a_track" );
+       return mlt_properties_get_int( mlt_transition_properties( this ), "a_track" );
 }
 
 /** Get the index of the b track.
@@ -112,50 +124,36 @@ int mlt_transition_get_a_track( mlt_transition this )
 
 int mlt_transition_get_b_track( mlt_transition this )
 {
-       mlt_properties properties = mlt_transition_properties( this );
-       return mlt_properties_get_int( properties, "b_track" );
+       return mlt_properties_get_int( mlt_transition_properties( this ), "b_track" );
 }
 
 /** 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( mlt_transition_properties( this ), "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( mlt_transition_properties( this ), "out" );
 }
 
 /** Process the frame.
+
+       If we have no process method (unlikely), we simply return the a_frame unmolested.
 */
 
-static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
+mlt_frame mlt_transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
 {
        if ( this->process == NULL )
-       {
-               if ( !mlt_frame_is_test_card( a_frame ) )
-               {
-                       mlt_frame_close( b_frame );
-                       return a_frame;
-               }
-               else
-               {
-                       mlt_frame_close( a_frame );
-                       return b_frame;
-               }
-       }
+               return a_frame;
        else
-       {
                return this->process( this, a_frame, b_frame );
-       }
 }
 
 /** Get a frame from this filter.
@@ -165,14 +163,12 @@ static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt
        method for all tracks, we have to take special care that we only obtain the a and
        b frames once - we do this on the first call to get a frame from either a or b.
        
-       After that, we have 3 cases to resolve:
+       After that, we have 2 cases to resolve:
        
        1)      if the track is the a_track and we're in the time zone, then we need to call the
-               process method to do the effect on the frame (we assign NULL to the a_frame and
-               b_frames here) otherwise, we pass on the a_frame unmolested;
-       2)      if the track is the b_track and we're the in the time zone OR the b_frame is NULL,
-               then we generate a test card frame, otherwise we pass on the b frame unmolested;
-       3)      For all other tracks, we get the frames on demand.
+               process method to do the effect on the frame and remember we've passed it on
+               otherwise, we pass on the a_frame unmolested;
+       2)      For all other tracks, we get the frames on demand.
 */
 
 static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
@@ -183,61 +179,45 @@ 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 ) &&
-                ( this->a_frame == NULL && this->b_frame == NULL ) )
+       if ( ( index == a_track || index == b_track ) && !( this->a_held || this->b_held ) )
        {
                mlt_service_get_frame( this->producer, &this->a_frame, a_track );
                mlt_service_get_frame( this->producer, &this->b_frame, b_track );
+               this->a_held = 1;
+               this->b_held = 1;
        }
        
        // Special case track processing
        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 );
-                       
-                       // Important - NULL both frames now so that we know they're done...
-                       this->a_frame = NULL;
-                       this->b_frame = NULL;
+                       *frame = mlt_transition_process( this, this->a_frame, this->b_frame );
+                       if ( !mlt_properties_get_int( mlt_frame_properties( this->a_frame ), "test_image" ) )
+                               mlt_properties_set_int( mlt_frame_properties( this->b_frame ), "test_image", 1 );
+                       if ( !mlt_properties_get_int( mlt_frame_properties( this->a_frame ), "test_audio" ) )
+                               mlt_properties_set_int( mlt_frame_properties( this->b_frame ), "test_audio", 1 );
+                       this->a_held = 0;
                }
                else
                {
                        // Pass on the 'a frame' and remember that we've done it
                        *frame = this->a_frame;
-                       this->a_frame = NULL;
-               }                       
+                       this->a_held = 0;
+               }
                return 0;
        }
        if ( index == b_track )
        {
-               if ( this->b_frame == NULL )
-               {
-                       // We're *probably* in the zone and the a frame has been requested
-                       *frame = mlt_frame_init( );
-               }
-               else
-               {
-                       mlt_timecode timecode = mlt_frame_get_timecode( this->b_frame );
-                       if ( timecode >= in && timecode < out )
-                       {
-                               // We're in the zone, but the 'a frame' has not been requested yet
-                               *frame = mlt_frame_init( );
-                       }
-                       else
-                       {
-                               // We're out of the zone, pass on b and remember that we've done it
-                               *frame = this->b_frame;
-                               this->b_frame = NULL;
-                       }
-               }
+               // Pass on the 'b frame' and remember that we've done it
+               *frame = this->b_frame;
+               this->b_held = 0;
                return 0;
        }
        else
@@ -252,8 +232,12 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i
 
 void mlt_transition_close( mlt_transition this )
 {
-       if ( this->close != NULL )
-               this->close( this );
-       else
-               mlt_service_close( &this->parent );
+       if ( this != NULL && mlt_properties_dec_ref( mlt_transition_properties( this ) ) <= 0 )
+       {
+               this->parent.close = NULL;
+               if ( this->close != NULL )
+                       this->close( this );
+               else
+                       mlt_service_close( &this->parent );
+       }
 }