#include <string.h>
#include <math.h>
-typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double softness );
+typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int softness, uint32_t step );
/** Geometry struct.
*/
// Create an empty geometries object
mlt_geometry geometry = mlt_geometry_init( );
- // 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 duration
+ mlt_position length = mlt_transition_get_length( this );
double cycle = mlt_properties_get_double( properties, "cycle" );
// Get the new style geometry string
/** Calculate the field delta for this frame - position between two frames.
*/
-static inline double delta_calculate( mlt_transition this, mlt_frame frame, mlt_position position )
-{
- // Get the in and out position
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
- double length = out - in + 1;
-
- // Now do the calcs
- double x = ( double )( position - in ) / length;
- double y = ( double )( position + 1 - in ) / length;
-
- return length * ( y - x ) / 2.0;
-}
-
static int get_value( mlt_properties properties, const char *preferred, const char *fallback )
{
int value = mlt_properties_get_int( properties, preferred );
*p++ = ( image[ i ] - 16 ) * 299; // 299 = 65535 / 219
}
-static inline int calculate_mix( uint16_t *luma, int j, double soft, int weight, int alpha )
+static inline int calculate_mix( uint16_t *luma, int j, int softness, int weight, int alpha, uint32_t step )
{
- int i_softness = soft * ( 1 << 16 );
- int w = ( ( 1 << 16 ) - 1 ) * weight / 100;
- uint32_t a = ( ( 1 << 16 ) - 1 ) * weight / 100 * ( 1.0 + soft );
- return ( ( luma ? smoothstep( luma[ j ], luma[ j ] + i_softness, a ) : w ) * alpha ) >> 8;
+ return ( ( luma ? smoothstep( luma[ j ], luma[ j ] + softness, step ) : weight ) * alpha ) >> 8;
}
static inline uint8_t sample_mix( uint8_t dest, uint8_t src, int mix )
/** Composite a source line over a destination line
*/
-static void composite_line_yuv( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
+static void composite_line_yuv( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft, uint32_t step )
{
register int j;
register int mix;
for ( j = 0; j < width; j ++ )
{
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ );
+ mix = calculate_mix( luma, j, soft, weight, *alpha_b ++, step );
*dest = sample_mix( *dest, *src++, mix );
dest++;
*dest = sample_mix( *dest, *src++, mix );
}
}
-static void composite_line_yuv_or( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
+static void composite_line_yuv_or( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft, uint32_t step )
{
register int j;
register int mix;
for ( j = 0; j < width; j ++ )
{
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ | *alpha_a );
+ mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ | *alpha_a, step );
*dest = sample_mix( *dest, *src++, mix );
dest++;
*dest = sample_mix( *dest, *src++, mix );
}
}
-static void composite_line_yuv_and( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
+static void composite_line_yuv_and( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft, uint32_t step )
{
register int j;
register int mix;
for ( j = 0; j < width; j ++ )
{
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ & *alpha_a );
+ mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ & *alpha_a, step );
*dest = sample_mix( *dest, *src++, mix );
dest++;
*dest = sample_mix( *dest, *src++, mix );
}
}
-static void composite_line_yuv_xor( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
+static void composite_line_yuv_xor( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft, uint32_t step )
{
register int j;
register int mix;
for ( j = 0; j < width; j ++ )
{
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ ^ *alpha_a );
+ mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ ^ *alpha_a, step );
*dest = sample_mix( *dest, *src++, mix );
dest++;
*dest = sample_mix( *dest, *src++, mix );
int bpp = 2;
int stride_src = geometry.sw * bpp;
int stride_dest = width_dest * bpp;
-
+ int i_softness = ( 1 << 16 ) * softness;
+ int weight = ( ( 1 << 16 ) - 1 ) * geometry.item.mix / 100;
+ uint32_t luma_step = ( ( 1 << 16 ) - 1 ) * geometry.item.mix / 100 * ( 1.0 + softness );
+
// Adjust to consumer scale
int x = rint( geometry.item.x * width_dest / geometry.nw );
int y = rint( geometry.item.y * height_dest / geometry.nh );
// now do the compositing only to cropped extents
for ( i = 0; i < height_src; i += step )
{
- line_fn( p_dest, p_src, width_src, alpha_b, alpha_a, geometry.item.mix, p_luma, softness );
+ line_fn( p_dest, p_src, width_src, alpha_b, alpha_a, weight, p_luma, i_softness, luma_step );
p_src += stride_src;
p_dest += stride_dest;
// Adjust to consumer scale
*width = rint( geometry->sw * *width / geometry->nw );
+ *width -= *width % 2; // coerce to even width for yuv422
*height = rint( geometry->sh * *height / geometry->nh );
// fprintf(stderr, "%s: scaled %dx%d norm %dx%d resize %dx%d\n", __FILE__,
// geometry->sw, geometry->sh, geometry->nw, geometry->nh, *width, *height);
ret = mlt_frame_get_image( b_frame, image, &format, width, height, 1 );
+ // composite_yuv uses geometry->sw to determine source stride, which
+ // should equal the image width if not using crop property.
+ if ( !mlt_properties_get( properties, "crop" ) )
+ geometry->sw = *width;
+
// Set the frame back
mlt_properties_set_int( b_props, "resize_alpha", resize_alpha );
if ( !crop )
{
crop = mlt_geometry_init();
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
- int length = out - in + 1;
+ mlt_position length = mlt_transition_get_length( this );
double cycle = mlt_properties_get_double( properties, "cycle" );
// Allow a geometry repeat cycle
}
else
{
- int length = mlt_transition_get_out( this ) - mlt_transition_get_in( this ) + 1;
+ mlt_position length = mlt_transition_get_length( this );
double cycle = mlt_properties_get_double( properties, "cycle" );
if ( cycle > 1 )
length = cycle;
uint8_t *dest = NULL;
// Get the image and dimensions
- uint8_t *image = mlt_properties_get_data( a_props, "image", NULL );
- int width = mlt_properties_get_int( a_props, "width" );
- int height = mlt_properties_get_int( a_props, "height" );
- int format = mlt_properties_get_int( a_props, "format" );
+ uint8_t *image = NULL;
+ int width = mlt_properties_get_int( a_props, "normalised_width" );
+ int height = mlt_properties_get_int( a_props, "normalised_height" );
+ mlt_image_format format = mlt_image_yuv422;
+
+ mlt_frame_get_image( a_frame, &image, &format, &width, &height, 0 );
+ if ( !image )
+ return b_frame;
// Pointers for copy operation
uint8_t *p;
dest = mlt_pool_alloc( w * h * 2 );
// Assign to the new frame
- mlt_properties_set_data( b_props, "image", dest, w * h * 2, mlt_pool_release, NULL );
+ mlt_frame_set_image( b_frame, dest, w * h * 2, mlt_pool_release );
mlt_properties_set_int( b_props, "width", w );
mlt_properties_set_int( b_props, "height", h );
mlt_properties_set_int( b_props, "format", format );
struct geometry_s result;
// Calculate the position
- double delta = delta_calculate( this, a_frame, position );
+ double delta = mlt_transition_get_progress_delta( this, a_frame );
// Get the image from the b frame
uint8_t *image_b = NULL;
- int width_b = *width;
- int height_b = *height;
+ int width_b = *width > 0 ? *width : mlt_properties_get_int( a_props, "normalised_width" );
+ int height_b = *height > 0 ? *height : mlt_properties_get_int( a_props, "normalised_height" );
// Vars for alphas
uint8_t *alpha_a = NULL;
int field;
double luma_softness = mlt_properties_get_double( properties, "softness" );
+ mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
uint16_t *luma_bitmap = get_luma( this, properties, width_b, height_b );
+ mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
char *operator = mlt_properties_get( properties, "operator" );
alpha_b = alpha_b == NULL ? mlt_frame_get_alpha_mask( b_frame ) : alpha_b;
// Use alignment (and hence alpha of b frame)
mlt_properties_set_int( properties, "aligned", 1 );
+ // Default to progressive rendering
+ mlt_properties_set_int( properties, "progressive", 1 );
+
// Inform apps and framework that this is a video only transition
mlt_properties_set_int( properties, "_transition_type", 1 );
}