#include "mlt_transition.h"
#include "mlt_frame.h"
#include "mlt_log.h"
+#include "mlt_producer.h"
#include <stdio.h>
#include <stdlib.h>
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
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 );
}
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;
}
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
}
// 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 ];
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 );