]> git.sesse.net Git - mlt/blobdiff - src/framework/mlt_transition.c
Minor modifications to compositing options and etv fx
[mlt] / src / framework / mlt_transition.c
index a571dfe8707b2f354dc061443ddcf9cb5ec39141..435fdb6c62a94b863c53ff1c36623f172838b13f 100644 (file)
@@ -42,18 +42,39 @@ int mlt_transition_init( mlt_transition this, void *child )
        this->child = child;
        if ( mlt_service_init( service, this ) == 0 )
        {
+               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_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 );
+
                return 0;
        }
        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.
@@ -61,7 +82,7 @@ mlt_service mlt_transition_service( mlt_transition this )
 
 mlt_properties mlt_transition_properties( mlt_transition this )
 {
-       return mlt_service_properties( mlt_transition_service( this ) );
+       return MLT_TRANSITION_PROPERTIES( this );
 }
 
 /** Connect this transition with a producers a and b tracks.
@@ -72,11 +93,10 @@ int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_tra
        int ret = mlt_service_connect_producer( &this->parent, producer, a_track );
        if ( ret == 0 )
        {
+               mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
                this->producer = producer;
-               this->a_track = a_track;
-               this->b_track = b_track;
-               this->in = 0;
-               this->out = 0;
+               mlt_properties_set_int( properties, "a_track", a_track );
+               mlt_properties_set_int( properties, "b_track", b_track );
        }
        return ret;
 }
@@ -84,10 +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 )
 {
-       this->in = in;
-       this->out = out;
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties_set_position( properties, "in", in );
+       mlt_properties_set_position( properties, "out", out );
 }
 
 /** Get the index of the a track.
@@ -95,7 +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 )
 {
-       return this->a_track;
+       return mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "a_track" );
 }
 
 /** Get the index of the b track.
@@ -103,47 +124,36 @@ int mlt_transition_get_a_track( mlt_transition this )
 
 int mlt_transition_get_b_track( mlt_transition this )
 {
-       return this->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 )
 {
-       return this->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 )
 {
-       return this->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.
@@ -153,72 +163,78 @@ 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 )
 {
        mlt_transition this = service->child;
 
-       // Fetch a and b frames together...
-       if ( ( index == this->a_track || index == this->b_track ) &&
-                ( this->a_frame == NULL && this->b_frame == NULL ) )
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+
+       int accepts_blanks = mlt_properties_get_int( properties, "_accepts_blanks" );
+       int a_track = mlt_properties_get_int( properties, "a_track" );
+       int b_track = mlt_properties_get_int( properties, "b_track" );
+       mlt_position in = mlt_properties_get_position( properties, "in" );
+       mlt_position out = mlt_properties_get_position( properties, "out" );
+       int always_active = mlt_properties_get_int( properties, "always_active" );
+
+       if ( ( index == a_track || index == b_track ) && !( this->a_held || this->b_held ) )
        {
-               mlt_service_get_frame( this->producer, &this->a_frame, this->a_track );
-               mlt_service_get_frame( this->producer, &this->b_frame, this->b_track );
+               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 == this->a_track )
+       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 >= this->in && timecode < this->out )
+               mlt_position position = mlt_frame_get_position( this->a_frame );
+               if ( always_active || ( 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;
+                       if ( !accepts_blanks && ( this->b_frame == NULL || ( mlt_frame_is_test_card( this->b_frame ) && mlt_frame_is_test_audio( this->b_frame ) ) ) )
+                       {
+                               *frame = this->a_frame;
+                       }
+                       else if ( !accepts_blanks && ( this->a_frame == NULL || ( mlt_frame_is_test_card( this->a_frame ) && mlt_frame_is_test_audio( this->a_frame ) ) ) )
+                       {
+                               mlt_frame t = this->a_frame;
+                               this->a_frame = this->b_frame;
+                               this->b_frame = t;
+                               *frame = this->a_frame;
+                       }
+                       else
+                       {
+                               int hide = 0;
+                               *frame = mlt_transition_process( this, this->a_frame, this->b_frame );
+                               if ( !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this->a_frame ), "test_image" ) )
+                                       hide = 1;
+                               if ( !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this->a_frame ), "test_audio" ) )
+                                       hide |= 2;
+                               mlt_properties_set_int( MLT_FRAME_PROPERTIES( this->b_frame ), "hide", hide );
+                       }
+                       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 == this->b_track )
+       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 >= this->in && timecode < this->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
@@ -233,8 +249,17 @@ 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 );
+                       free( this );
+               }
+       }
 }