mlt_transition transition_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { mlt_transition transition = calloc( 1, sizeof( struct mlt_transition_s ) ); if ( transition != NULL && mlt_transition_init( transition, NULL ) == 0 ) { transition->process = transition_process; if ( arg != NULL ) mlt_properties_set_double( MLT_TRANSITION_PROPERTIES( transition ), "start", atof( arg ) ); // Inform apps and framework that this is an audio only transition mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 2 ); } return transition; }
mlt_transition transition_movit_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { mlt_transition transition = NULL; GlslManager* glsl = GlslManager::get_instance(); if ( glsl && ( transition = mlt_transition_new() ) ) { transition->process = process; mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "mix", arg ); // Inform apps and framework that this is a video only transition mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 1 ); } return transition; }
mlt_transition transition_affine_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { mlt_transition transition = mlt_transition_new( ); if ( transition != NULL ) { mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "distort", 0 ); mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "geometry", "0/0:100%x100%" ); // Inform apps and framework that this is a video only transition mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 1 ); transition->process = transition_process; } return transition; }
static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){ if (*format!=mlt_image_yuv422 ){ return -1; } mlt_frame b_frame = mlt_frame_pop_frame( a_frame ); mlt_transition transition = mlt_frame_pop_service( a_frame ); mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); int invert = mlt_properties_get_int( properties, "invert" ); if ( mlt_properties_get( a_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( a_props, "rescale.interp" ), "none" ) ) mlt_properties_set( a_props, "rescale.interp", "nearest" ); // set consumer_aspect_ratio for a and b frame if ( mlt_properties_get_double( a_props, "aspect_ratio" ) == 0.0 ) mlt_properties_set_double( a_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ); if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 ) mlt_properties_set_double( b_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ); mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ); if ( mlt_properties_get( b_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( b_props, "rescale.interp" ), "none" ) ) mlt_properties_set( b_props, "rescale.interp", "nearest" ); uint8_t *images[]={NULL,NULL,NULL}; mlt_frame_get_image( a_frame, &images[0], format, width, height, 1 ); mlt_frame_get_image( b_frame, &images[1], format, width, height, 1 ); mlt_position in = mlt_transition_get_in( transition ); mlt_position out = mlt_transition_get_out( transition ); // Get the position of the frame char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" ); mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( a_frame ), name ); float pos=( float )( position - in ) / ( float )( out - in + 1 ); process_frei0r_item( transition_type , pos , properties, !invert ? a_frame : b_frame , images , format, width,height, writable ); *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" ); *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" ); *image = mlt_properties_get_data( !invert ? a_props : b_props , "image", NULL ); return 0; }
mlt_transition transition_region_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { // Create a new transition mlt_transition transition = mlt_transition_new( ); // Further initialisation if ( transition != NULL ) { // Get the properties from the transition mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); // Assign the transition process method transition->process = transition_process; // Default factory mlt_properties_set( properties, "factory", mlt_environment( "MLT_PRODUCER" ) ); // Resource defines the shape of the region mlt_properties_set( properties, "resource", arg == NULL ? "rectangle" : arg ); // Inform apps and framework that this is a video only transition mlt_properties_set_int( properties, "_transition_type", 1 ); } // Return the transition return transition; }
static mlt_frame process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame ) { mlt_service service = MLT_TRANSITION_SERVICE(transition); if ( !GlslManager::init_chain( service ) ) { // Create the Movit effect chain EffectChain* chain = GlslManager::get_chain( service ); mlt_profile profile = mlt_service_profile( service ); Input* b_input = new MltInput( profile->width, profile->height ); ImageFormat output_format; output_format.color_space = COLORSPACE_sRGB; output_format.gamma_curve = GAMMA_sRGB; chain->add_input( b_input ); chain->add_output( output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED ); chain->set_dither_bits( 8 ); Effect* effect = chain->add_effect( new OverlayEffect(), GlslManager::get_input( service ), b_input ); // Save these new input on properties for get_image mlt_properties_set_data( MLT_TRANSITION_PROPERTIES(transition), "movit input B", b_input, 0, NULL, NULL ); } // Push the transition on to the frame mlt_frame_push_service( a_frame, transition ); // Push the b_frame on to the stack mlt_frame_push_frame( a_frame, b_frame ); // Push the transition method mlt_frame_push_get_image( a_frame, get_image ); return a_frame; }
static void add_text_to_bg( mlt_producer producer, mlt_frame bg_frame, mlt_frame text_frame ) { mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_transition transition = mlt_properties_get_data( producer_properties, "_transition", NULL ); if( !transition ) { mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ); transition = mlt_factory_transition( profile, "composite", NULL ); // Save the transition for future use. mlt_properties_set_data( producer_properties, "_transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL ); // Configure the transition. mlt_properties transition_properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_properties_set( transition_properties, "geometry", "0%/0%:100%x100%:100" ); mlt_properties_set( transition_properties, "halign", "center" ); mlt_properties_set( transition_properties, "valign", "middle" ); } if( transition && bg_frame && text_frame ) { // Apply the transition. mlt_transition_process( transition, bg_frame, text_frame ); } }
static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){ mlt_frame b_frame = mlt_frame_pop_frame( a_frame ); mlt_transition transition = mlt_frame_pop_service( a_frame ); mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); int invert = mlt_properties_get_int( properties, "invert" ); uint8_t *images[]={NULL,NULL,NULL}; *format = mlt_image_rgb24a; mlt_frame_get_image( a_frame, &images[0], format, width, height, 0 ); mlt_frame_get_image( b_frame, &images[1], format, width, height, 0 ); double position = mlt_transition_get_position( transition, a_frame ); mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) ); double time = position / mlt_profile_fps( profile ); process_frei0r_item( MLT_TRANSITION_SERVICE(transition), position, time, properties, !invert ? a_frame : b_frame, images, width, height ); *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" ); *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" ); *image = mlt_properties_get_data( !invert ? a_props : b_props , "image", NULL ); return 0; }
mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame ) { char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" ); mlt_properties_set_position( MLT_FRAME_PROPERTIES( a_frame ), name, mlt_frame_get_position( a_frame ) ); mlt_frame_push_service( a_frame, transition ); mlt_frame_push_frame( a_frame, b_frame ); mlt_frame_push_get_image( a_frame, transition_get_image ); return a_frame; }
mlt_service MLTWebVfx::createTransition() { mlt_transition self = mlt_transition_new(); if (self) { self->process = transitionProcess; // Video only transition mlt_properties_set_int(MLT_TRANSITION_PROPERTIES(self), "_transition_type", 1); return MLT_TRANSITION_SERVICE(self); } return 0; }
static void setup_transition( mlt_filter filter, mlt_transition transition ) { mlt_properties my_properties = MLT_FILTER_PROPERTIES( filter ); mlt_properties transition_properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_properties_set( transition_properties, "geometry", mlt_properties_get( my_properties, "geometry" ) ); mlt_properties_set( transition_properties, "halign", mlt_properties_get( my_properties, "halign" ) ); mlt_properties_set( transition_properties, "valign", mlt_properties_get( my_properties, "valign" ) ); mlt_properties_set_int( transition_properties, "out", mlt_properties_get_int( my_properties, "_out" ) ); mlt_properties_set_int( transition_properties, "refresh", 1 ); }
int mlt_transition_connect( mlt_transition self, mlt_service producer, int a_track, int b_track ) { int ret = mlt_service_connect_producer( &self->parent, producer, a_track ); if ( ret == 0 ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( self ); self->producer = producer; mlt_properties_set_int( properties, "a_track", a_track ); mlt_properties_set_int( properties, "b_track", b_track ); } return ret; }
mlt_transition transition_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { transition_mix mix = calloc( 1 , sizeof( struct transition_mix_s ) ); mlt_transition transition = calloc( 1, sizeof( struct mlt_transition_s ) ); if ( mix && transition && !mlt_transition_init( transition, mix ) ) { mix->parent = transition; transition->close = transition_close; transition->process = transition_process; if ( arg ) mlt_properties_set_double( MLT_TRANSITION_PROPERTIES( transition ), "start", atof( arg ) ); // Inform apps and framework that this is an audio only transition mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 2 ); } else { if ( transition ) mlt_transition_close( transition ); if ( mix ) free( mix ); } return transition; }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the filter mlt_filter filter = mlt_frame_pop_service( frame ); // Get the properties of the filter mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); // Get the region transition mlt_transition transition = mlt_properties_get_data( properties, "_transition", NULL ); // Create the transition if not available if ( transition == NULL ) { // Create the transition mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) ); transition = mlt_factory_transition( profile, "region", NULL ); // Register with the filter mlt_properties_set_data( properties, "_transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL ); // Pass a reference to this filter down mlt_properties_set_data( MLT_TRANSITION_PROPERTIES( transition ), "_region_filter", filter, 0, NULL, NULL ); } mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); // Pass all properties down mlt_properties_inherit( MLT_TRANSITION_PROPERTIES( transition ), properties ); // Make the frame's position relative to this filter's in point mlt_frame_set_position( frame, mlt_filter_get_position( filter, frame ) ); // Process the frame mlt_transition_process( transition, frame, NULL ); return mlt_frame_get_image( frame, image, format, width, height, writable ); }
static inline void get_affine( affine_t *affine, mlt_transition transition, double position, int length ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); int keyed = mlt_properties_get_int( properties, "keyed" ); if ( keyed == 0 ) { double fix_rotate_x = anim_get_angle( properties, "fix_rotate_x", position, length ); double fix_rotate_y = anim_get_angle( properties, "fix_rotate_y", position, length ); double fix_rotate_z = anim_get_angle( properties, "fix_rotate_z", position, length ); double rotate_x = mlt_properties_get_double( properties, "rotate_x" ); double rotate_y = mlt_properties_get_double( properties, "rotate_y" ); double rotate_z = mlt_properties_get_double( properties, "rotate_z" ); double fix_shear_x = anim_get_angle( properties, "fix_shear_x", position, length ); double fix_shear_y = anim_get_angle( properties, "fix_shear_y", position, length ); double fix_shear_z = anim_get_angle( properties, "fix_shear_z", position, length ); double shear_x = mlt_properties_get_double( properties, "shear_x" ); double shear_y = mlt_properties_get_double( properties, "shear_y" ); double shear_z = mlt_properties_get_double( properties, "shear_z" ); double ox = mlt_properties_anim_get_double( properties, "ox", position, length ); double oy = mlt_properties_anim_get_double( properties, "oy", position, length ); affine_rotate_x( affine->matrix, fix_rotate_x + rotate_x * position ); affine_rotate_y( affine->matrix, fix_rotate_y + rotate_y * position ); affine_rotate_z( affine->matrix, fix_rotate_z + rotate_z * position ); affine_shear( affine->matrix, fix_shear_x + shear_x * position, fix_shear_y + shear_y * position, fix_shear_z + shear_z * position ); affine_offset( affine->matrix, ox, oy ); } else { double rotate_x = anim_get_angle(properties, "rotate_x", position, length); double rotate_y = anim_get_angle(properties, "rotate_y", position, length); double rotate_z = anim_get_angle(properties, "rotate_z", position, length); double shear_x = anim_get_angle(properties, "shear_x", position, length); double shear_y = anim_get_angle(properties, "shear_y", position, length); double shear_z = anim_get_angle(properties, "shear_z", position, length); double o_x = mlt_properties_anim_get_double(properties, "ox", repeat_position(properties, "ox", position, length), length); double o_y = mlt_properties_anim_get_double(properties, "oy", repeat_position(properties, "oy", position, length), length); affine_rotate_x( affine->matrix, rotate_x ); affine_rotate_y( affine->matrix, rotate_y ); affine_rotate_z( affine->matrix, rotate_z ); affine_shear( affine->matrix, shear_x, shear_y, shear_z ); affine_offset( affine->matrix, o_x, o_y ); } }
static inline void get_affine( affine_t *affine, mlt_transition transition, float position ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); int keyed = mlt_properties_get_int( properties, "keyed" ); if ( keyed == 0 ) { float fix_rotate_x = mlt_properties_get_double( properties, "fix_rotate_x" ); float fix_rotate_y = mlt_properties_get_double( properties, "fix_rotate_y" ); float fix_rotate_z = mlt_properties_get_double( properties, "fix_rotate_z" ); float rotate_x = mlt_properties_get_double( properties, "rotate_x" ); float rotate_y = mlt_properties_get_double( properties, "rotate_y" ); float rotate_z = mlt_properties_get_double( properties, "rotate_z" ); float fix_shear_x = mlt_properties_get_double( properties, "fix_shear_x" ); float fix_shear_y = mlt_properties_get_double( properties, "fix_shear_y" ); float fix_shear_z = mlt_properties_get_double( properties, "fix_shear_z" ); float shear_x = mlt_properties_get_double( properties, "shear_x" ); float shear_y = mlt_properties_get_double( properties, "shear_y" ); float shear_z = mlt_properties_get_double( properties, "shear_z" ); float ox = mlt_properties_get_double( properties, "ox" ); float oy = mlt_properties_get_double( properties, "oy" ); affine_rotate_x( affine->matrix, fix_rotate_x + rotate_x * position ); affine_rotate_y( affine->matrix, fix_rotate_y + rotate_y * position ); affine_rotate_z( affine->matrix, fix_rotate_z + rotate_z * position ); affine_shear( affine->matrix, fix_shear_x + shear_x * position, fix_shear_y + shear_y * position, fix_shear_z + shear_z * position ); affine_offset( affine->matrix, ox, oy ); } else { float rotate_x = composite_calculate_key( transition, "rotate_x", "rotate_x_info", 360, position ); float rotate_y = composite_calculate_key( transition, "rotate_y", "rotate_y_info", 360, position ); float rotate_z = composite_calculate_key( transition, "rotate_z", "rotate_z_info", 360, position ); float shear_x = composite_calculate_key( transition, "shear_x", "shear_x_info", 360, position ); float shear_y = composite_calculate_key( transition, "shear_y", "shear_y_info", 360, position ); float shear_z = composite_calculate_key( transition, "shear_z", "shear_z_info", 360, position ); float o_x = composite_calculate_key( transition, "ox", "ox_info", 0, position ); float o_y = composite_calculate_key( transition, "oy", "oy_info", 0, position ); affine_rotate_x( affine->matrix, rotate_x ); affine_rotate_y( affine->matrix, rotate_y ); affine_rotate_z( affine->matrix, rotate_z ); affine_shear( affine->matrix, shear_x, shear_y, shear_z ); affine_offset( affine->matrix, o_x, o_y ); } }
void mlt_transition_close( mlt_transition self ) { if ( self != NULL && mlt_properties_dec_ref( MLT_TRANSITION_PROPERTIES( self ) ) <= 0 ) { self->parent.close = NULL; if ( self->close != NULL ) { self->close( self ); } else { mlt_service_close( &self->parent ); free( self->frames ); free( self ); } } }
static mlt_frame process(mlt_filter filter, mlt_frame frame) { mlt_properties properties = MLT_FILTER_PROPERTIES(filter); mlt_transition transition = mlt_properties_get_data(properties, "instance", NULL); char *name = mlt_properties_get(MLT_FILTER_PROPERTIES(filter), "transition"); if (!name || !strcmp("", name)) return frame; // Create the transition if needed. if (!transition || !mlt_properties_get(MLT_FILTER_PROPERTIES(transition), "mlt_service") || strcmp(name, mlt_properties_get(MLT_FILTER_PROPERTIES(transition), "mlt_service"))) { mlt_profile profile = mlt_service_profile(MLT_FILTER_SERVICE(filter)); transition = mlt_factory_transition(profile, name, NULL); mlt_properties_set_data(MLT_FILTER_PROPERTIES(filter), "instance", transition, 0, (mlt_destructor) mlt_transition_close, NULL); } if (transition) { mlt_properties transition_props = MLT_TRANSITION_PROPERTIES(transition); int type = mlt_properties_get_int(transition_props, "_transition_type"); int hide = mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame), "hide"); mlt_properties_pass_list(transition_props, properties, "in out"); mlt_properties_pass(transition_props, properties, "transition." ); // Only if video transition on visible track. if ((type & 1) && !mlt_frame_is_test_card(frame) && !(hide & 1)) { mlt_frame_push_service_int(frame, mlt_image_format_id(mlt_properties_get(properties, "mlt_image_format"))); mlt_frame_push_service(frame, transition); mlt_frame_push_get_image(frame, get_image); } if (type == 0) mlt_properties_debug(transition_props, "unknown transition type", stderr); } else { mlt_properties_debug(properties, "mask_failed to create transition", stderr ); } return frame; }
mlt_transition mlt_factory_transition( mlt_profile profile, const char *service, const void *input ) { mlt_transition obj = NULL; // Offer the application the chance to 'create' mlt_events_fire( event_object, "transition-create-request", service, input, &obj, NULL ); if ( obj == NULL ) { obj = mlt_repository_create( repository, profile, transition_type, service, input ); mlt_events_fire( event_object, "transition-create-done", service, input, obj, NULL ); } if ( obj != NULL ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( obj ); set_common_properties( properties, profile, "transition", service ); } return obj; }
static void geometry_calculate( mlt_transition transition, const char *store, struct mlt_geometry_item_s *output, double position ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_geometry geometry = mlt_properties_get_data( properties, store, NULL ); int mirror_off = mlt_properties_get_int( properties, "mirror_off" ); int repeat_off = mlt_properties_get_int( properties, "repeat_off" ); int length = mlt_geometry_get_length( geometry ); // Allow wrapping if ( !repeat_off && position >= length && length != 0 ) { int section = position / length; position -= section * length; if ( !mirror_off && section % 2 == 1 ) position = length - position; } // Fetch the key for the position mlt_geometry_fetch( geometry, output, position ); }
mlt_transition transition_vqm_init( mlt_profile profile, mlt_service_type type, const char *id, void *arg ) { mlt_transition transition = mlt_transition_new(); if ( transition ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); if ( !createQApplicationIfNeeded( MLT_TRANSITION_SERVICE(transition) ) ) { mlt_transition_close( transition ); return NULL; } transition->process = process; mlt_properties_set_int( properties, "_transition_type", 1 ); // video only mlt_properties_set_int( properties, "window_size", 8 ); printf( "frame psnr[Y] psnr[Cb] psnr[Cr] ssim[Y] ssim[Cb] ssim[Cr]\n" ); } return transition; }
static mlt_geometry transition_parse_keys( mlt_transition transition, const char *name, const char *store, int normalised_width, int normalised_height ) { // Get the properties of the transition mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); // Try to fetch it first mlt_geometry geometry = mlt_properties_get_data( properties, store, NULL ); // Determine length and obtain cycle mlt_position length = mlt_transition_get_length( transition ); double cycle = mlt_properties_get_double( properties, "cycle" ); // Allow a geometry repeat cycle if ( cycle >= 1 ) length = cycle; else if ( cycle > 0 ) length *= cycle; if ( geometry == NULL ) { // Get the new style geometry string char *property = mlt_properties_get( properties, name ); // Create an empty geometries object geometry = mlt_geometry_init( ); // Parse the geometry if we have one mlt_geometry_parse( geometry, property, length, normalised_width, normalised_height ); // Store it mlt_properties_set_data( properties, store, geometry, 0, ( mlt_destructor )mlt_geometry_close, NULL ); } else { // Check for updates and refresh if necessary mlt_geometry_refresh( geometry, mlt_properties_get( properties, name ), length, normalised_width, normalised_height ); } return geometry; }
int mlt_transition_init( mlt_transition self, void *child ) { mlt_service service = &self->parent; memset( self, 0, sizeof( struct mlt_transition_s ) ); self->child = child; if ( mlt_service_init( service, self ) == 0 ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( self ); service->get_frame = transition_get_frame; service->close = ( mlt_destructor )mlt_transition_close; service->close_object = self; 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; }
static int transition_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { // Get the b frame from the stack mlt_frame b_frame = mlt_frame_pop_audio( frame ); // Get the effect mlt_transition effect = mlt_frame_pop_audio( frame ); // Get the properties of the b frame mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); // We can only mix s16 *format = mlt_audio_s16; if ( mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( effect ), "combine" ) == 0 ) { double mix_start = 0.5, mix_end = 0.5; if ( mlt_properties_get( b_props, "audio.previous_mix" ) != NULL ) mix_start = mlt_properties_get_double( b_props, "audio.previous_mix" ); if ( mlt_properties_get( b_props, "audio.mix" ) != NULL ) mix_end = mlt_properties_get_double( b_props, "audio.mix" ); if ( mlt_properties_get_int( b_props, "audio.reverse" ) ) { mix_start = 1 - mix_start; mix_end = 1 - mix_end; } mix_audio( frame, b_frame, mix_start, mix_end, buffer, format, frequency, channels, samples ); } else { combine_audio( frame, b_frame, buffer, format, frequency, channels, samples ); } return 0; }
#include <stdlib.h> #include <ctype.h> #include <string.h> #include <math.h> /** Calculate the position for this frame. */ static float position_calculate( mlt_transition this, mlt_frame frame ) { // Get the in and out position mlt_position in = mlt_transition_get_in( this ); mlt_position out = mlt_transition_get_out( this ); // Get the position of the frame char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( this ), "_unique_id" ); mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), name ); // Now do the calcs return ( float )( position - in ) / ( float )( out - in + 1 ); } /** Calculate the field delta for this frame - position between two frames. */ static float delta_calculate( mlt_transition this, mlt_frame frame ) { // Get the in and out position mlt_position in = mlt_transition_get_in( this ); mlt_position out = mlt_transition_get_out( this );
static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_frame b_frame = mlt_frame_pop_frame( a_frame ); mlt_properties properties = MLT_FRAME_PROPERTIES( a_frame ); mlt_transition transition = MLT_TRANSITION( mlt_frame_pop_service( a_frame ) ); uint8_t *b_image; int window_size = mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( transition ), "window_size" ); double psnr[3], ssim[3]; *format = mlt_image_yuv422; mlt_frame_get_image( b_frame, &b_image, format, width, height, writable ); mlt_frame_get_image( a_frame, image, format, width, height, writable ); psnr[0] = calc_psnr( *image, b_image, *width * *height, 2 ); psnr[1] = calc_psnr( *image + 1, b_image + 1, *width * *height / 2, 4 ); psnr[2] = calc_psnr( *image + 3, b_image + 3, *width * *height / 2, 4 ); ssim[0] = calc_ssim( *image, b_image, *width, *height, window_size, 2 ); ssim[1] = calc_ssim( *image + 1, b_image + 1, *width / 2, *height, window_size, 4 ); ssim[2] = calc_ssim( *image + 3, b_image + 3, *width / 2, *height, window_size, 4 ); mlt_properties_set_double( properties, "meta.vqm.psnr.y", psnr[0] ); mlt_properties_set_double( properties, "meta.vqm.psnr.cb", psnr[1] ); mlt_properties_set_double( properties, "meta.vqm.psnr.cr", psnr[2] ); mlt_properties_set_double( properties, "meta.vqm.ssim.y", ssim[0] ); mlt_properties_set_double( properties, "meta.vqm.ssim.cb", ssim[1] ); mlt_properties_set_double( properties, "meta.vqm.ssim.cr", ssim[2] ); printf( "%05d %05.2f %05.2f %05.2f %5.3f %5.3f %5.3f\n", mlt_frame_get_position( a_frame ), psnr[0], psnr[1], psnr[2], ssim[0], ssim[1], ssim[2] ); // copy the B frame to the bottom of the A frame for comparison window_size = mlt_image_format_size( *format, *width, *height, NULL ) / 2; memcpy( *image + window_size, b_image + window_size, window_size ); if ( !mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( transition ), "render" ) ) return 0; // get RGBA image for Qt drawing *format = mlt_image_rgb24a; mlt_frame_get_image( a_frame, image, format, width, height, 1 ); // convert mlt image to qimage QImage img( *width, *height, QImage::Format_ARGB32 ); int y = *height + 1; uint8_t *src = *image; while ( --y ) { QRgb *dst = (QRgb*) img.scanLine( *height - y ); int x = *width + 1; while ( --x ) { *dst++ = qRgba( src[0], src[1], src[2], 255 ); src += 4; } } // setup Qt drawing QPainter painter; painter.begin( &img ); painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing ); // draw some stuff with Qt QPalette palette; QFont font; QString s; font.setBold( true ); font.setPointSize( 30 * *height / 1080 ); painter.setPen( QColor("black") ); painter.drawLine( 0, *height/2 + 1, *width, *height/2 ); painter.setPen( QColor("white") ); painter.drawLine( 0, *height/2 - 1, *width, *height/2 ); painter.setFont( font ); s.sprintf( "Frame: %05d\nPSNR: %05.2f (Y) %05.2f (Cb) %05.2f (Cr)\nSSIM: %5.3f (Y) %5.3f (Cb) %5.3f (Cr)", mlt_frame_get_position( a_frame ), psnr[0], psnr[1], psnr[2], ssim[0], ssim[1], ssim[2] ); painter.setPen( QColor("black") ); painter.drawText( 52, *height * 8 / 10 + 2, *width, *height, 0, s ); painter.setPen( QColor("white") ); painter.drawText( 50, *height * 8 / 10, *width, *height, 0, s ); // finish Qt drawing painter.end(); window_size = mlt_image_format_size( *format, *width, *height, NULL ); uint8_t *dst = (uint8_t *) mlt_pool_alloc( window_size ); mlt_properties_set_data( MLT_FRAME_PROPERTIES(a_frame), "image", dst, window_size, mlt_pool_release, NULL ); *image = dst; // convert qimage to mlt y = *height + 1; while ( --y ) { QRgb *src = (QRgb*) img.scanLine( *height - y ); int x = *width + 1; while ( --x ) { *dst++ = qRed( *src ); *dst++ = qGreen( *src ); *dst++ = qBlue( *src ); *dst++ = qAlpha( *src ); src++; } } return 0; }
static void * load_lib( mlt_profile profile, mlt_service_type type , void* handle){ int i=0; void (*f0r_get_plugin_info)(f0r_plugin_info_t*), *f0r_construct , *f0r_update , *f0r_destruct, (*f0r_get_param_info)(f0r_param_info_t* info, int param_index), (*f0r_init)(void) , *f0r_deinit , (*f0r_set_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index), (*f0r_get_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index), (*f0r_update2) (f0r_instance_t instance, double time, const uint32_t* inframe1, const uint32_t* inframe2,const uint32_t* inframe3, uint32_t* outframe); if ( ( f0r_construct = dlsym(handle, "f0r_construct") ) && (f0r_update = dlsym(handle,"f0r_update") ) && (f0r_destruct = dlsym(handle,"f0r_destruct") ) && (f0r_get_plugin_info = dlsym(handle,"f0r_get_plugin_info") ) && (f0r_get_param_info = dlsym(handle,"f0r_get_param_info") ) && (f0r_set_param_value= dlsym(handle,"f0r_set_param_value" ) ) && (f0r_get_param_value= dlsym(handle,"f0r_get_param_value" ) ) && (f0r_init= dlsym(handle,"f0r_init" ) ) && (f0r_deinit= dlsym(handle,"f0r_deinit" ) ) ){ f0r_update2=dlsym(handle,"f0r_update2"); f0r_plugin_info_t info; f0r_get_plugin_info(&info); void* ret=NULL; mlt_properties properties=NULL; if (type == producer_type && info.plugin_type == F0R_PLUGIN_TYPE_SOURCE ){ mlt_producer this = mlt_producer_new( ); if ( this != NULL ) { this->get_frame = producer_get_frame; this->close = ( mlt_destructor )producer_close; f0r_init(); properties=MLT_PRODUCER_PROPERTIES ( this ); for (i=0;i<info.num_params;i++){ f0r_param_info_t pinfo; f0r_get_param_info(&pinfo,i); } ret=this; } } else if (type == filter_type && info.plugin_type == F0R_PLUGIN_TYPE_FILTER ){ mlt_filter this = mlt_filter_new( ); if ( this != NULL ) { this->process = filter_process; this->close = filter_close; f0r_init(); properties=MLT_FILTER_PROPERTIES ( this ); for (i=0;i<info.num_params;i++){ f0r_param_info_t pinfo; f0r_get_param_info(&pinfo,i); } ret=this; } }else if (type == transition_type && info.plugin_type == F0R_PLUGIN_TYPE_MIXER2){ mlt_transition transition = mlt_transition_new( ); if ( transition != NULL ) { transition->process = transition_process; transition->close = transition_close; properties=MLT_TRANSITION_PROPERTIES( transition ); mlt_properties_set_int(properties, "_transition_type", 1 ); ret=transition; } } mlt_properties_set_data(properties, "_dlclose_handle", handle , sizeof (void*) , NULL , NULL ); mlt_properties_set_data(properties, "_dlclose", dlclose , sizeof (void*) , NULL , NULL ); mlt_properties_set_data(properties, "f0r_construct", f0r_construct , sizeof(void*),NULL,NULL); mlt_properties_set_data(properties, "f0r_update", f0r_update , sizeof(void*),NULL,NULL); if (f0r_update2) mlt_properties_set_data(properties, "f0r_update2", f0r_update2 , sizeof(void*),NULL,NULL); mlt_properties_set_data(properties, "f0r_destruct", f0r_destruct , sizeof(void*),NULL,NULL); mlt_properties_set_data(properties, "f0r_get_plugin_info", f0r_get_plugin_info , sizeof(void*),NULL,NULL); mlt_properties_set_data(properties, "f0r_get_param_info", f0r_get_param_info , sizeof(void*),NULL,NULL); mlt_properties_set_data(properties, "f0r_set_param_value", f0r_set_param_value , sizeof(void*),NULL,NULL); mlt_properties_set_data(properties, "f0r_get_param_value", f0r_get_param_value , sizeof(void*),NULL,NULL); return ret; }else{ printf("some was wrong\n"); dlerror(); } return NULL; }
int invert = mlt_properties_get_int( properties, "invert" ); uint8_t *images[]={NULL,NULL,NULL}; *format = mlt_image_rgb24a; mlt_frame_get_image( a_frame, &images[0], format, width, height, 0 ); mlt_frame_get_image( b_frame, &images[1], format, width, height, 0 ); double position = mlt_transition_get_position( transition, a_frame ); mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) ); double time = position / mlt_profile_fps( profile ); process_frei0r_item( MLT_TRANSITION_SERVICE(transition), position, time, properties, !invert ? a_frame : b_frame, images, width, height ); *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" ); *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" ); *image = mlt_properties_get_data( !invert ? a_props : b_props , "image", NULL ); return 0; } mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame ) { mlt_frame_push_service( a_frame, transition ); mlt_frame_push_frame( a_frame, b_frame ); mlt_frame_push_get_image( a_frame, transition_get_image ); return a_frame; } void transition_close( mlt_transition this ){ destruct ( MLT_TRANSITION_PROPERTIES ( this ) ); }
static int transition_get_audio( mlt_frame frame_a, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { int error = 0; // Get the b frame from the stack mlt_frame frame_b = mlt_frame_pop_audio( frame_a ); // Get the effect mlt_transition transition = mlt_frame_pop_audio( frame_a ); // Get the properties of the b frame mlt_properties b_props = MLT_FRAME_PROPERTIES( frame_b ); transition_mix self = transition->child; int16_t *buffer_b, *buffer_a; int frequency_b = *frequency, frequency_a = *frequency; int channels_b = *channels, channels_a = *channels; int samples_b = *samples, samples_a = *samples; // We can only mix s16 *format = mlt_audio_s16; mlt_frame_get_audio( frame_b, (void**) &buffer_b, format, &frequency_b, &channels_b, &samples_b ); mlt_frame_get_audio( frame_a, (void**) &buffer_a, format, &frequency_a, &channels_a, &samples_a ); if ( buffer_b == buffer_a ) { *samples = samples_b; *channels = channels_b; *buffer = buffer_b; *frequency = frequency_b; return error; } int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame_a ), "silent_audio" ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame_a ), "silent_audio", 0 ); if ( silent ) memset( buffer_a, 0, samples_a * channels_a * sizeof( int16_t ) ); silent = mlt_properties_get_int( b_props, "silent_audio" ); mlt_properties_set_int( b_props, "silent_audio", 0 ); if ( silent ) memset( buffer_b, 0, samples_b * channels_b * sizeof( int16_t ) ); // determine number of samples to process *samples = MIN( self->src_buffer_count + samples_b, self->dest_buffer_count + samples_a ); *channels = MIN( MIN( channels_b, channels_a ), MAX_CHANNELS ); *frequency = frequency_a; // Prevent src buffer overflow by discarding oldest samples. samples_b = MIN( samples_b, MAX_SAMPLES * MAX_CHANNELS / channels_b ); size_t bytes = PCM16_BYTES( samples_b, channels_b ); if ( PCM16_BYTES( self->src_buffer_count + samples_b, channels_b ) > MAX_BYTES ) { mlt_log_verbose( MLT_TRANSITION_SERVICE(transition), "buffer overflow: src_buffer_count %d\n", self->src_buffer_count ); self->src_buffer_count = MAX_SAMPLES * MAX_CHANNELS / channels_b - samples_b; memmove( self->src_buffer, &self->src_buffer[MAX_SAMPLES * MAX_CHANNELS - samples_b * channels_b], PCM16_BYTES( samples_b, channels_b ) ); } // Buffer new src samples. memcpy( &self->src_buffer[self->src_buffer_count * channels_b], buffer_b, bytes ); self->src_buffer_count += samples_b; buffer_b = self->src_buffer; // Prevent dest buffer overflow by discarding oldest samples. samples_a = MIN( samples_a, MAX_SAMPLES * MAX_CHANNELS / channels_a ); bytes = PCM16_BYTES( samples_a, channels_a ); if ( PCM16_BYTES( self->dest_buffer_count + samples_a, channels_a ) > MAX_BYTES ) { mlt_log_verbose( MLT_TRANSITION_SERVICE(transition), "buffer overflow: dest_buffer_count %d\n", self->dest_buffer_count ); self->dest_buffer_count = MAX_SAMPLES * MAX_CHANNELS / channels_a - samples_a; memmove( self->dest_buffer, &self->dest_buffer[MAX_SAMPLES * MAX_CHANNELS - samples_a * channels_a], PCM16_BYTES( samples_a, channels_a ) ); } // Buffer the new dest samples. memcpy( &self->dest_buffer[self->dest_buffer_count * channels_a], buffer_a, bytes ); self->dest_buffer_count += samples_a; buffer_a = self->dest_buffer; // Do the mixing. if ( mlt_properties_get_int( MLT_TRANSITION_PROPERTIES(transition), "combine" ) ) { double weight = 1.0; if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame_a ), "meta.mixdown" ) ) weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame_a ), "meta.volume" ); combine_audio( weight, buffer_a, buffer_b, channels_a, channels_b, *channels, *samples ); } else { double mix_start = 0.5, mix_end = 0.5; if ( mlt_properties_get( b_props, "audio.previous_mix" ) ) mix_start = mlt_properties_get_double( b_props, "audio.previous_mix" ); if ( mlt_properties_get( b_props, "audio.mix" ) ) mix_end = mlt_properties_get_double( b_props, "audio.mix" ); if ( mlt_properties_get_int( b_props, "audio.reverse" ) ) { mix_start = 1.0 - mix_start; mix_end = 1.0 - mix_end; } mix_audio( mix_start, mix_end, buffer_a, buffer_b, channels_a, channels_b, *channels, *samples ); } // Copy the audio into the frame. bytes = PCM16_BYTES( *samples, *channels ); *buffer = mlt_pool_alloc( bytes ); memcpy( *buffer, buffer_a, bytes ); mlt_frame_set_audio( frame_a, *buffer, *format, bytes, mlt_pool_release ); if ( mlt_properties_get_int( b_props, "_speed" ) == 0 ) { // Flush the buffer when paused and scrubbing. samples_b = self->src_buffer_count; samples_a = self->dest_buffer_count; } else { // Determine the maximum amount of latency permitted in the buffer. int max_latency = CLAMP( *frequency / 1000, 0, MAX_SAMPLES ); // samples in 1ms // samples_b becomes the new target src buffer count. samples_b = CLAMP( self->src_buffer_count - *samples, 0, max_latency ); // samples_b becomes the number of samples to consume: difference between actual and the target. samples_b = self->src_buffer_count - samples_b; // samples_a becomes the new target dest buffer count. samples_a = CLAMP( self->dest_buffer_count - *samples, 0, max_latency ); // samples_a becomes the number of samples to consume: difference between actual and the target. samples_a = self->dest_buffer_count - samples_a; } // Consume the src buffer. self->src_buffer_count -= samples_b; if ( self->src_buffer_count ) { memmove( self->src_buffer, &self->src_buffer[samples_b * channels_b], PCM16_BYTES( self->src_buffer_count, channels_b )); } // Consume the dest buffer. self->dest_buffer_count -= samples_a; if ( self->dest_buffer_count ) { memmove( self->dest_buffer, &self->dest_buffer[samples_a * channels_a], PCM16_BYTES( self->dest_buffer_count, channels_a )); } return error; }
static mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame ) { mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); // Only if mix is specified, otherwise a producer may set the mix if ( mlt_properties_get( properties, "start" ) ) { // Determine the time position of this frame in the transition duration mlt_properties props = mlt_properties_get_data( MLT_FRAME_PROPERTIES( b_frame ), "_producer", NULL ); mlt_position in = mlt_properties_get_int( props, "in" ); mlt_position out = mlt_properties_get_int( props, "out" ); int length = mlt_properties_get_int( properties, "length" ); mlt_position time = mlt_properties_get_int( props, "_frame" ); double mix = mlt_transition_get_progress( transition, b_frame ); if ( mlt_properties_get_int( properties, "always_active" ) ) mix = ( double ) ( time - in ) / ( double ) ( out - in + 1 ); // TODO: Check the logic here - shouldn't we be computing current and next mixing levels in all cases? if ( length == 0 ) { // If there is an end mix level adjust mix to the range if ( mlt_properties_get( properties, "end" ) ) { double start = mlt_properties_get_double( properties, "start" ); double end = mlt_properties_get_double( properties, "end" ); mix = start + ( end - start ) * mix; } // A negative means total crossfade (uses position) else if ( mlt_properties_get_double( properties, "start" ) >= 0 ) { // Otherwise, start/constructor is a constant mix level mix = mlt_properties_get_double( properties, "start" ); } // Finally, set the mix property on the frame mlt_properties_set_double( b_props, "audio.mix", mix ); // Initialise transition previous mix value to prevent an inadvertant jump from 0 mlt_position last_position = mlt_properties_get_position( properties, "_last_position" ); mlt_position current_position = mlt_frame_get_position( b_frame ); mlt_properties_set_position( properties, "_last_position", current_position ); if ( !mlt_properties_get( properties, "_previous_mix" ) || current_position != last_position + 1 ) mlt_properties_set_double( properties, "_previous_mix", mix ); // Tell b frame what the previous mix level was mlt_properties_set_double( b_props, "audio.previous_mix", mlt_properties_get_double( properties, "_previous_mix" ) ); // Save the current mix level for the next iteration mlt_properties_set_double( properties, "_previous_mix", mlt_properties_get_double( b_props, "audio.mix" ) ); mlt_properties_set_double( b_props, "audio.reverse", mlt_properties_get_double( properties, "reverse" ) ); } else { double level = mlt_properties_get_double( properties, "start" ); double mix_start = level; double mix_end = mix_start; double mix_increment = 1.0 / length; if ( time - in < length ) { mix_start = mix_start * ( ( double )( time - in ) / length ); mix_end = mix_start + mix_increment; } else if ( time > out - length ) { mix_end = mix_start * ( ( double )( out - time - in ) / length ); mix_start = mix_end - mix_increment; } mix_start = mix_start < 0 ? 0 : mix_start > level ? level : mix_start; mix_end = mix_end < 0 ? 0 : mix_end > level ? level : mix_end; mlt_properties_set_double( b_props, "audio.previous_mix", mix_start ); mlt_properties_set_double( b_props, "audio.mix", mix_end ); } } // Override the get_audio method mlt_frame_push_audio( a_frame, transition ); mlt_frame_push_audio( a_frame, b_frame ); mlt_frame_push_audio( a_frame, transition_get_audio ); return a_frame; }