X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fframework%2Fmlt_transition.c;h=86a57d4ea4cf30ab5b4ce444986940e7cf0f07a9;hb=3181f81620bdd95bec5555f70fbb344a7cfaed5b;hp=707a87891bb842a050220c28691973370448f4d2;hpb=13eb988ea37cf62a08cdfd73fa42186eefe8ad64;p=mlt diff --git a/src/framework/mlt_transition.c b/src/framework/mlt_transition.c index 707a8789..86a57d4e 100644 --- a/src/framework/mlt_transition.c +++ b/src/framework/mlt_transition.c @@ -24,6 +24,7 @@ #include "mlt_transition.h" #include "mlt_frame.h" #include "mlt_log.h" +#include "mlt_producer.h" #include #include @@ -205,7 +206,24 @@ mlt_position mlt_transition_get_length( mlt_transition self ) return ( out > 0 ) ? ( out - in + 1 ) : 0; } -/** Get the relative position of a frame. +/** Get the position within the transition. + * + * The position is relative to the in point. + * + * \public \memberof mlt_transition_s + * \param self a transition + * \param frame a frame + * \return the position + */ + +mlt_position mlt_transition_get_position( mlt_transition self, mlt_frame frame ) +{ + mlt_position in = mlt_transition_get_in( self ); + mlt_position position = mlt_frame_get_position( frame ); + return position - in; +} + +/** Get the percent complete. * * \public \memberof mlt_transition_s * \param self a transition @@ -216,11 +234,21 @@ mlt_position mlt_transition_get_length( mlt_transition self ) double mlt_transition_get_progress( mlt_transition self, mlt_frame frame ) { double progress = 0; + mlt_position in = mlt_transition_get_in( self ); mlt_position out = mlt_transition_get_out( self ); + if ( out == 0 ) + { + // If always active, use the frame's producer + mlt_producer producer = mlt_frame_get_original_producer( frame ); + if ( producer ) + { + in = mlt_producer_get_in( producer ); + out = mlt_producer_get_out( producer ); + } + } if ( out != 0 ) { - mlt_position in = mlt_transition_get_in( self ); mlt_position position = mlt_frame_get_position( frame ); progress = ( double ) ( position - in ) / ( double ) ( out - in + 1 ); } @@ -238,16 +266,26 @@ double mlt_transition_get_progress( mlt_transition self, mlt_frame frame ) double mlt_transition_get_progress_delta( mlt_transition self, mlt_frame frame ) { double progress = 0; + mlt_position in = mlt_transition_get_in( self ); mlt_position out = mlt_transition_get_out( self ); + if ( out == 0 ) + { + // If always active, use the frame's producer + mlt_producer producer = mlt_frame_get_original_producer( frame ); + if ( producer ) + { + in = mlt_producer_get_in( producer ); + out = mlt_producer_get_out( producer ); + } + } if ( out != 0 ) { - mlt_position in = mlt_transition_get_in( self ); mlt_position position = mlt_frame_get_position( frame ); double length = out - in + 1; double x = ( double ) ( position - in ) / length; double y = ( double ) ( position + 1 - in ) / length; - progress = length * ( y - x ) / 2.0; + progress = ( y - x ) / 2.0; } return progress; } @@ -271,6 +309,49 @@ mlt_frame mlt_transition_process( mlt_transition self, mlt_frame a_frame, mlt_fr return self->process( self, a_frame, b_frame ); } +static int get_image_a( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +{ + mlt_transition self = mlt_frame_pop_service( a_frame ); + mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); + + // All transitions get scaling + const char *rescale = mlt_properties_get( a_props, "rescale.interp" ); + if ( !rescale || !strcmp( rescale, "none" ) ) + mlt_properties_set( a_props, "rescale.interp", "nearest" ); + + // Ensure sane aspect ratio + if ( mlt_frame_get_aspect_ratio( a_frame ) == 0.0 ) + mlt_frame_set_aspect_ratio( a_frame, mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(self) ) ) ); + + return mlt_frame_get_image( a_frame, image, format, width, height, writable ); +} + +static int get_image_b( mlt_frame b_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +{ + mlt_transition self = mlt_frame_pop_service( b_frame ); + mlt_frame a_frame = mlt_frame_pop_frame( b_frame ); + mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); + mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); + + // Set scaling from A frame if not already provided. + if ( !mlt_properties_get( b_props, "rescale.interp" ) ) + { + const char *rescale = mlt_properties_get( a_props, "rescale.interp" ); + if ( !rescale || !strcmp( rescale, "none" ) ) + rescale = "nearest"; + mlt_properties_set( b_props, "rescale.interp", rescale ); + } + + // Ensure sane aspect ratio + if ( mlt_frame_get_aspect_ratio( b_frame ) == 0.0 ) + mlt_frame_set_aspect_ratio( b_frame, mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(self) ) ) ); + + mlt_properties_pass_list( b_props, a_props, + "consumer_deinterlace, deinterlace_method, consumer_tff" ); + + return mlt_frame_get_image( b_frame, image, format, width, height, writable ); +} + /** Get a frame from a transition. The logic is complex here. A transition is typically applied to frames on the a and @@ -390,7 +471,7 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i } // Finally, process the a and b frames - if ( active ) + if ( active && !mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( self ), "disable" ) ) { mlt_frame a_frame_ptr = self->frames[ !reverse_order ? a_frame : b_frame ]; mlt_frame b_frame_ptr = self->frames[ !reverse_order ? b_frame : a_frame ]; @@ -398,6 +479,13 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i int b_hide = mlt_properties_get_int( MLT_FRAME_PROPERTIES( b_frame_ptr ), "hide" ); if ( !( a_hide & type ) && !( b_hide & type ) ) { + // Add hooks for pre-processing frames + mlt_frame_push_service( a_frame_ptr, self ); + mlt_frame_push_get_image( a_frame_ptr, get_image_a ); + mlt_frame_push_frame( b_frame_ptr, a_frame_ptr ); + mlt_frame_push_service( b_frame_ptr, self ); + mlt_frame_push_get_image( b_frame_ptr, get_image_b ); + // Process the transition *frame = mlt_transition_process( self, a_frame_ptr, b_frame_ptr );