X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Fcore%2Ftransition_composite.c;h=12b07103e1903da99ea2e8c8cbfc512a38561611;hb=b2737f448f85593413049ae846fa27e6ecc5bf35;hp=3725c4a62c548f0c32dd745e4ae9ab3426674a5d;hpb=fffd43713488179eeb1770d2d94ec0177252fef5;p=mlt diff --git a/src/modules/core/transition_composite.c b/src/modules/core/transition_composite.c index 3725c4a6..12b07103 100644 --- a/src/modules/core/transition_composite.c +++ b/src/modules/core/transition_composite.c @@ -27,7 +27,7 @@ #include #include -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 ); +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. */ @@ -201,7 +201,7 @@ static inline double delta_calculate( mlt_transition this, mlt_frame frame, mlt_ return length * ( y - x ) / 2.0; } -static int get_value( mlt_properties properties, char *preferred, char *fallback ) +static int get_value( mlt_properties properties, const char *preferred, const char *fallback ) { int value = mlt_properties_get_int( properties, preferred ); if ( value == 0 ) @@ -368,9 +368,9 @@ static void luma_read_yuv422( uint8_t *image, uint16_t **map, int width, int hei *p++ = ( image[ i ] - 16 ) * 299; // 299 = 65535 / 219 } -static inline int calculate_mix( uint16_t *luma, int j, int soft, int weight, int alpha ) +static inline int calculate_mix( uint16_t *luma, int j, int softness, int weight, int alpha, uint32_t step ) { - return ( ( ( luma == NULL ) ? weight : smoothstep( luma[ j ], luma[ j ] + soft, weight + soft ) ) * 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 ) @@ -381,14 +381,14 @@ 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, int 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 ); @@ -398,14 +398,14 @@ static void composite_line_yuv( uint8_t *dest, uint8_t *src, int width, uint8_t } } -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 ) +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 ); @@ -414,14 +414,14 @@ static void composite_line_yuv_or( uint8_t *dest, uint8_t *src, int width, uint8 } } -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 ) +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 ); @@ -430,14 +430,14 @@ static void composite_line_yuv_and( uint8_t *dest, uint8_t *src, int width, uint } } -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 ) +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 ); @@ -449,18 +449,20 @@ static void composite_line_yuv_xor( uint8_t *dest, uint8_t *src, int width, uint /** Composite function. */ -static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint8_t *p_src, int width_src, int height_src, uint8_t *alpha_b, uint8_t *alpha_a, struct geometry_s geometry, int field, uint16_t *p_luma, int32_t softness, composite_line_fn line_fn ) +static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint8_t *p_src, int width_src, int height_src, uint8_t *alpha_b, uint8_t *alpha_a, struct geometry_s geometry, int field, uint16_t *p_luma, double softness, composite_line_fn line_fn ) { int ret = 0; int i; int x_src = -geometry.x_src, y_src = -geometry.y_src; int uneven_x_src = ( x_src % 2 ); - int32_t weight = ( ( 1 << 16 ) - 1 ) * ( geometry.item.mix / 100 ); int step = ( field > -1 ) ? 2 : 1; 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 ); @@ -566,7 +568,7 @@ static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint // 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, weight, 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; @@ -648,6 +650,15 @@ static uint16_t* get_luma( mlt_transition this, mlt_properties properties, int w luma_bitmap = NULL; } } + else { + char *old_luma = mlt_properties_get( properties, "_luma" ); + if ( old_luma && old_luma[0] ) + { + mlt_properties_set_data( properties, "_luma.orig_bitmap", NULL, 0, NULL, NULL ); + luma_bitmap = NULL; + mlt_properties_set( properties, "_luma", NULL); + } + } if ( resource && resource[0] && ( luma_bitmap == NULL || luma_width != width || luma_height != height ) ) { @@ -848,6 +859,11 @@ static int get_b_frame_image( mlt_transition this, mlt_frame b_frame, uint8_t ** 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 ); @@ -1129,7 +1145,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f uint8_t *alpha_b = NULL; // Composites always need scaling... defaulting to lowest - char *rescale = mlt_properties_get( a_props, "rescale.interp" ); + const char *rescale = mlt_properties_get( a_props, "rescale.interp" ); if ( rescale == NULL || !strcmp( rescale, "none" ) ) rescale = "nearest"; mlt_properties_set( a_props, "rescale.interp", rescale ); @@ -1137,8 +1153,9 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f // Do the calculation // NB: Locks needed here since the properties are being modified + int invert = mlt_properties_get_int( properties, "invert" ); mlt_service_lock( MLT_TRANSITION_SERVICE( this ) ); - composite_calculate( this, &result, a_frame, position ); + composite_calculate( this, &result, invert ? b_frame : a_frame, position ); mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) ); // Since we are the consumer of the b_frame, we must pass along these @@ -1166,7 +1183,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f } // Get the image from the a frame - mlt_frame_get_image( a_frame, image, format, width, height, 1 ); + mlt_frame_get_image( a_frame, invert ? &image_b : image, format, width, height, 1 ); alpha_a = mlt_frame_get_alpha_mask( a_frame ); // Optimisation - no compositing required @@ -1196,7 +1213,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f height_b = mlt_properties_get_int( a_props, "dest_height" ); } - if ( *image != image_b && ( image_b != NULL || get_b_frame_image( this, b_frame, &image_b, &width_b, &height_b, &result ) == 0 ) ) + if ( *image != image_b && ( ( invert ? 0 : image_b ) || get_b_frame_image( this, b_frame, invert ? image : &image_b, &width_b, &height_b, &result ) == 0 ) ) { uint8_t *dest = *image; uint8_t *src = image_b; @@ -1205,7 +1222,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f mlt_properties_get_int( properties, "progressive" ); int field; - int32_t luma_softness = mlt_properties_get_double( properties, "softness" ) * ( 1 << 16 ); + double luma_softness = mlt_properties_get_double( properties, "softness" ); uint16_t *luma_bitmap = get_luma( this, properties, width_b, height_b ); char *operator = mlt_properties_get( properties, "operator" ); @@ -1239,7 +1256,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f // Do the calculation if we need to // NB: Locks needed here since the properties are being modified mlt_service_lock( MLT_TRANSITION_SERVICE( this ) ); - composite_calculate( this, &result, a_frame, field_position ); + composite_calculate( this, &result, invert ? b_frame : a_frame, field_position ); mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) ); if ( mlt_properties_get_int( properties, "titles" ) ) @@ -1267,7 +1284,10 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f } // Composite the b_frame on the a_frame - composite_yuv( dest, *width, *height, src, width_b, height_b, alpha_b, alpha_a, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn ); + if ( invert ) + composite_yuv( dest, width_b, height_b, src, *width, *height, alpha_a, alpha_b, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn ); + else + composite_yuv( dest, *width, *height, src, width_b, height_b, alpha_b, alpha_a, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn ); } } } @@ -1321,7 +1341,7 @@ mlt_transition transition_composite_init( mlt_profile profile, mlt_service_type mlt_properties_set( properties, "start", arg != NULL ? arg : "0,0:100%x100%" ); // Default factory - mlt_properties_set( properties, "factory", "fezzik" ); + mlt_properties_set( properties, "factory", mlt_environment( "MLT_PRODUCER" ) ); // Use alignment (and hence alpha of b frame) mlt_properties_set_int( properties, "aligned", 1 );