Sundry minor fixes and optimisations
[melted] / src / modules / core / transition_composite.c
index e35d365..16bf590 100644 (file)
@@ -103,12 +103,17 @@ static mlt_geometry transition_parse_keys( mlt_transition this, int normalised_w
        // Get the in and out position
        mlt_position in = mlt_transition_get_in( this );
        mlt_position out = mlt_transition_get_out( this );
+       int length = out - in + 1;
 
        // Get the new style geometry string
        char *property = mlt_properties_get( properties, "geometry" );
 
+       // Allow a geometry repeat cycle
+       if ( mlt_properties_get_int( properties, "cycle" ) )
+               length = mlt_properties_get_int( properties, "cycle" );
+
        // Parse the geometry if we have one
-       mlt_geometry_parse( geometry, property, out - in + 1, normalised_width, normalised_height );
+       mlt_geometry_parse( geometry, property, length, normalised_width, normalised_height );
 
        // Check if we're using the old style geometry
        if ( property == NULL )
@@ -379,8 +384,8 @@ void composite_line_yuv( uint8_t *dest, uint8_t *src, int width_src, uint8_t *al
        for ( j = 0; j < width_src; j ++ )
        {
                a = ( alpha == NULL ) ? 255 : *alpha ++;
-               mix = ( luma == NULL ) ? weight : linearstep( luma[ j ], luma[ j ] + softness, weight );
-               mix = ( mix * ( a + 1 ) ) >> 8;
+               mix = ( luma == NULL ) ? weight : smoothstep( luma[ j ], luma[ j ] + softness, weight + softness );
+               mix = ( mix * a ) >> 8;
                *dest = ( *src++ * mix + *dest * ( ( 1 << 16 ) - mix ) ) >> 16;
                dest++;
                *dest = ( *src++ * mix + *dest * ( ( 1 << 16 ) - mix ) ) >> 16;
@@ -458,7 +463,6 @@ static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint
        // field 1 = upper field and y should be even.
        if ( ( field > -1 ) && ( y % 2 == field ) )
        {
-               //fprintf( stderr, "field %d y %d\n", field, y );
                if ( ( field == 1 && y < height_dest - 1 ) || ( field == 0 && y == 0 ) )
                        p_dest += stride_dest;
                else
@@ -523,7 +527,7 @@ static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint
 */
 
 static inline void
-scale_luma ( uint16_t *dest_buf, int dest_width, int dest_height, const uint16_t *src_buf, int src_width, int src_height )
+scale_luma ( uint16_t *dest_buf, int dest_width, int dest_height, const uint16_t *src_buf, int src_width, int src_height, int invert )
 {
        register int i, j;
        register int x_step = ( src_width << 16 ) / dest_width;
@@ -537,7 +541,7 @@ scale_luma ( uint16_t *dest_buf, int dest_width, int dest_height, const uint16_t
                
                for ( j = 0; j < dest_width; j++ )
                {
-                       *dest_buf++ = src[ x >> 16 ];
+                       *dest_buf++ = src[ x >> 16 ] ^ invert;
                        x += x_step;
                }
                y += y_step;
@@ -550,6 +554,7 @@ static uint16_t* get_luma( mlt_properties properties, int width, int height )
        int luma_width = mlt_properties_get_int( properties, "_luma.width" );
        int luma_height = mlt_properties_get_int( properties, "_luma.height" );
        uint16_t *luma_bitmap = mlt_properties_get_data( properties, "_luma.bitmap", NULL );
+       int invert = mlt_properties_get_int( properties, "luma_invert" );
        
        // If the filename property changed, reload the map
        char *resource = mlt_properties_get( properties, "luma" );
@@ -643,7 +648,7 @@ static uint16_t* get_luma( mlt_properties properties, int width, int height )
                }
                // Scale luma map
                luma_bitmap = mlt_pool_alloc( width * height * sizeof( uint16_t ) );
-               scale_luma( luma_bitmap, width, height, orig_bitmap, luma_width, luma_height );
+               scale_luma( luma_bitmap, width, height, orig_bitmap, luma_width, luma_height, invert * ( ( 1 << 16 ) - 1 ) );
 
                // Remember the scaled luma size to prevent unnecessary scaling
                mlt_properties_set_int( properties, "_luma.width", width );
@@ -665,7 +670,7 @@ static int get_b_frame_image( mlt_transition this, mlt_frame b_frame, uint8_t **
        mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
        mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
 
-       if ( mlt_properties_get( properties, "distort" ) == NULL && mlt_properties_get( b_props, "distort" ) == NULL && geometry->item.distort == 0 )
+       if ( mlt_properties_get_int( properties, "distort" ) == 0 && mlt_properties_get_int( b_props, "distort" ) == 0 && geometry->item.distort == 0 )
        {
                // Adjust b_frame pixel aspect
                int normalised_width = geometry->item.w;
@@ -689,12 +694,20 @@ static int get_b_frame_image( mlt_transition this, mlt_frame b_frame, uint8_t **
                        scaled_height = normalised_height;
                }
 
-               // Now apply the fill
-               // TODO: Should combine fill/distort in one property
-               if ( mlt_properties_get( properties, "fill" ) != NULL )
+               // Honour the fill request - this will scale the image to fill width or height while maintaining a/r
+               // ????: Shouln't this be the default behaviour?
+               if ( mlt_properties_get_int( properties, "fill" ) )
                {
-                       scaled_width = ( geometry->item.w / scaled_width ) * scaled_width;
-                       scaled_height = ( geometry->item.h / scaled_height ) * scaled_height;
+                       if ( scaled_height < normalised_height && scaled_width * normalised_height / scaled_height < normalised_width )
+                       {
+                               scaled_width = scaled_width * normalised_height / scaled_height;
+                               scaled_height = normalised_height;
+                       }
+                       else if ( scaled_width < normalised_width && scaled_height * normalised_width / scaled_width < normalised_height )
+                       {
+                               scaled_height = scaled_height * normalised_width / scaled_width;
+                               scaled_width = normalised_width;
+                       }
                }
 
                // Save the new scaled dimensions
@@ -708,7 +721,7 @@ static int get_b_frame_image( mlt_transition this, mlt_frame b_frame, uint8_t **
        }
 
        // We want to ensure that we bypass resize now...
-       mlt_properties_set( b_props, "distort", "true" );
+       mlt_properties_set_int( b_props, "distort", 1 );
 
        // Take into consideration alignment for optimisation
        if ( !mlt_properties_get_int( properties, "titles" ) )
@@ -762,6 +775,8 @@ static mlt_geometry composite_calculate( mlt_transition this, struct geometry_s
        else
        {
                int length = mlt_transition_get_out( this ) - mlt_transition_get_in( this ) + 1;
+               if ( mlt_properties_get_int( properties, "cycle" ) )
+                       length = mlt_properties_get_int( properties, "cycle" );
                mlt_geometry_refresh( start, mlt_properties_get( properties, "geometry" ), length, normalised_width, normalised_height );
        }
 
@@ -893,7 +908,7 @@ mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_pos
 
        // Assign this position to the b frame
        mlt_frame_set_position( b_frame, frame_position );
-       mlt_properties_set( b_props, "distort", "true" );
+       mlt_properties_set_int( b_props, "distort", 1 );
 
        // Return the frame
        return b_frame;
@@ -972,7 +987,6 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                {
                        if ( mlt_properties_get( b_props, "rescale.interp" ) == NULL )
                                mlt_properties_set( b_props, "rescale.interp", "hyper" );
-                       mlt_properties_set( properties, "fill", NULL );
                        width_b = mlt_properties_get_int( a_props, "dest_width" );
                        height_b = mlt_properties_get_int( a_props, "dest_height" );
                }
@@ -1002,8 +1016,10 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
 
                                if ( mlt_properties_get_int( properties, "titles" ) )
                                {
-                                       result.nw = result.item.w = *width;
-                                       result.nh = result.item.h = *height;
+                                       result.item.w = *width * ( result.item.w / result.nw );
+                                       result.nw = result.item.w;
+                                       result.item.h = *height * ( result.item.h / result.nh );
+                                       result.nh = *height;
                                        result.sw = width_b;
                                        result.sh = height_b;
                                }
@@ -1053,7 +1069,7 @@ mlt_transition transition_composite_init( char *arg )
                this->process = composite_process;
                
                // Default starting motion and zoom
-               mlt_properties_set( properties, "start", arg != NULL ? arg : "85%,5%:10%x10%" );
+               mlt_properties_set( properties, "start", arg != NULL ? arg : "0,0:100%x100%" );
                
                // Default factory
                mlt_properties_set( properties, "factory", "fezzik" );