/** Composite function.
*/
-static int composite_yuv( uint8_t *p_dest, mlt_image_format format_dest, int width_dest, int height_dest, mlt_frame that, struct geometry_s geometry )
+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 *p_alpha, struct geometry_s geometry )
{
int ret = 0;
- uint8_t *p_src;
int i, j;
- int stride_src;
- int stride_dest;
int x_src = 0, y_src = 0;
-
- mlt_image_format format_src = format_dest;
float weight = geometry.mix / 100;
-
- // Compute the dimensioning rectangle
- mlt_properties b_props = mlt_frame_properties( that );
- mlt_transition this = mlt_properties_get_data( b_props, "transition_composite", NULL );
- mlt_properties properties = mlt_transition_properties( this );
-
- if ( mlt_properties_get( properties, "distort" ) == NULL )
- {
- // Now do additional calcs based on real_width/height etc
- //int normalised_width = mlt_properties_get_int( b_props, "normalised_width" );
- //int normalised_height = mlt_properties_get_int( b_props, "normalised_height" );
- int normalised_width = geometry.w;
- int normalised_height = geometry.h;
- int real_width = get_value( b_props, "real_width", "width" );
- int real_height = get_value( b_props, "real_height", "height" );
- double input_ar = mlt_frame_get_aspect_ratio( that );
- double output_ar = mlt_properties_get_double( b_props, "consumer_aspect_ratio" );
- int scaled_width = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_width;
- int scaled_height = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_height;
-
- // Now ensure that our images fit in the normalised frame
- if ( scaled_width > normalised_width )
- {
- scaled_height = scaled_height * normalised_width / scaled_width;
- scaled_width = normalised_width;
- }
- if ( scaled_height > normalised_height )
- {
- scaled_width = scaled_width * normalised_height / scaled_height;
- scaled_height = normalised_height;
- }
-
- // Special case
- if ( scaled_height == normalised_height )
- scaled_width = normalised_width;
-
- // Now we need to align to the geometry
- if ( scaled_width <= geometry.w && scaled_height <= geometry.h )
- {
- // TODO: Should take into account requested alignment here...
- // Assume centred alignment for now
-
- geometry.x = geometry.x + ( geometry.w - scaled_width ) / 2;
- geometry.y = geometry.y + ( geometry.h - scaled_height ) / 2;
- geometry.w = scaled_width;
- geometry.h = scaled_height;
- mlt_properties_set( b_props, "distort", "true" );
- }
- else
- {
- mlt_properties_set( b_props, "distort", "true" );
- }
- }
- else
- {
- // We want to ensure that we bypass resize now...
- mlt_properties_set( b_props, "distort", "true" );
- }
-
int x = ( geometry.x * width_dest ) / geometry.nw;
int y = ( geometry.y * height_dest ) / geometry.nh;
- int width_src = ( geometry.w * width_dest ) / geometry.nw;
- int height_src = ( geometry.h * height_dest ) / geometry.nh;
+ int stride_src = width_src * 2;
+ int stride_dest = width_dest * 2;
x -= x % 2;
if ( ( x < 0 && -x >= width_src ) || ( y < 0 && -y >= height_src ) )
return ret;
- format_src = mlt_image_yuv422;
- format_dest = mlt_image_yuv422;
-
- mlt_frame_get_image( that, &p_src, &format_src, &width_src, &height_src, 1 /* writable */ );
-
- stride_src = width_src * 2;
- stride_dest = width_dest * 2;
-
// crop overlay off the left edge of frame
if ( x < 0 )
{
// offset pointer into frame buffer based upon positive, even coordinates only!
p_dest += ( x < 0 ? 0 : x ) * 2 + ( y < 0 ? 0 : y ) * stride_dest;
- // Get the alpha channel of the overlay
- uint8_t *p_alpha = mlt_frame_get_alpha_mask( that );
-
// offset pointer into alpha channel based upon cropping
if ( p_alpha )
p_alpha += x_src + y_src * stride_src / 2;
}
+/** Get the properly sized image from b_frame.
+*/
+
+static int get_b_frame_image( mlt_frame b_frame, uint8_t **image, int *width, int *height, struct geometry_s *geometry )
+{
+ int ret = 0;
+ mlt_image_format format = mlt_image_yuv422;
+
+ // Compute the dimensioning rectangle
+ mlt_properties b_props = mlt_frame_properties( b_frame );
+ mlt_transition this = mlt_properties_get_data( b_props, "transition_composite", NULL );
+ mlt_properties properties = mlt_transition_properties( this );
+
+ if ( mlt_properties_get( properties, "distort" ) == NULL )
+ {
+ // Now do additional calcs based on real_width/height etc
+ //int normalised_width = mlt_properties_get_int( b_props, "normalised_width" );
+ //int normalised_height = mlt_properties_get_int( b_props, "normalised_height" );
+ int normalised_width = geometry->w;
+ int normalised_height = geometry->h;
+ int real_width = get_value( b_props, "real_width", "width" );
+ int real_height = get_value( b_props, "real_height", "height" );
+ double input_ar = mlt_frame_get_aspect_ratio( b_frame );
+ double output_ar = mlt_properties_get_double( b_props, "consumer_aspect_ratio" );
+ int scaled_width = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_width;
+ int scaled_height = ( input_ar > output_ar ? input_ar / output_ar : output_ar / input_ar ) * real_height;
+
+ // Now ensure that our images fit in the normalised frame
+ if ( scaled_width > normalised_width )
+ {
+ scaled_height = scaled_height * normalised_width / scaled_width;
+ scaled_width = normalised_width;
+ }
+ if ( scaled_height > normalised_height )
+ {
+ scaled_width = scaled_width * normalised_height / scaled_height;
+ scaled_height = normalised_height;
+ }
+
+ // Special case
+ if ( scaled_height == normalised_height )
+ scaled_width = normalised_width;
+
+ // Now we need to align to the geometry
+ if ( scaled_width <= geometry->w && scaled_height <= geometry->h )
+ {
+ // TODO: Should take into account requested alignment here...
+ // Assume centred alignment for now
+
+ geometry->x = geometry->x + ( geometry->w - scaled_width ) / 2;
+ geometry->y = geometry->y + ( geometry->h - scaled_height ) / 2;
+ geometry->w = scaled_width;
+ geometry->h = scaled_height;
+ mlt_properties_set( b_props, "distort", "true" );
+ }
+ else
+ {
+ mlt_properties_set( b_props, "distort", "true" );
+ }
+ }
+ else
+ {
+ // We want to ensure that we bypass resize now...
+ mlt_properties_set( b_props, "distort", "true" );
+ }
+
+ int x = ( geometry->x * *width ) / geometry->nw;
+ int y = ( geometry->y * *height ) / geometry->nh;
+ *width = ( geometry->w * *width ) / geometry->nw;
+ *height = ( geometry->h * *height ) / geometry->nh;
+
+ x -= x % 2;
+
+ // optimization points - no work to do
+ if ( *width <= 0 || *height <= 0 )
+ return 1;
+
+ if ( ( x < 0 && -x >= *width ) || ( y < 0 && -y >= *height ) )
+ return 1;
+
+ ret = mlt_frame_get_image( b_frame, image, &format, width, height, 1 /* writable */ );
+
+ return ret;
+}
+
+
/** Get the image.
*/
// Get the b frame from the stack
mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
+ // This compositer is yuv422 only
+ *format = mlt_image_yuv422;
+
// Get the image from the a frame
mlt_frame_get_image( a_frame, image, format, width, height, 1 );
// consumer properties from the a_frame
mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
mlt_properties_set_double( b_props, "consumer_scale", mlt_properties_get_double( a_props, "consumer_scale" ) );
-
- // Composite the b_frame on the a_frame
- composite_yuv( *image, *format, *width, *height, b_frame, result );
+
+ // Get the image from the b frame
+ uint8_t *image_b;
+ int width_b = *width;
+ int height_b = *height;
+ if ( get_b_frame_image( b_frame, &image_b, &width_b, &height_b, &result ) == 0 )
+ {
+ uint8_t *alpha = mlt_frame_get_alpha_mask( b_frame );
+
+ // Composite the b_frame on the a_frame
+ composite_yuv( *image, *width, *height, image_b, width_b, height_b, alpha, result );
+ }
}
return 0;
int luma_height = mlt_properties_get_int( b_props, "luma.height" );
float *luma_bitmap = mlt_properties_get_data( b_props, "luma.bitmap", NULL );
float luma_softness = mlt_properties_get_double( b_props, "luma.softness" );
- int progressive = mlt_properties_get_int( b_props, "progressive" );
+ int progressive = mlt_properties_get_int( b_props, "progressive" ) || mlt_properties_get_int( a_props, "consumer_progressive" );
int top_field_first = mlt_properties_get_int( b_props, "top_field_first" );
int reverse = mlt_properties_get_int( b_props, "luma.reverse" );
// Since we are the consumer of the b_frame, we must pass along this
// consumer property from the a_frame
- mlt_properties_set_double( b_props, "consumer_aspect_ratio",
- mlt_properties_get_double( mlt_frame_properties( this ), "consumer_aspect_ratio" ) );
- mlt_properties_set_double( b_props, "consumer_scale",
- mlt_properties_get_double( mlt_frame_properties( this ), "consumer_scale" ) );
+ mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
+ mlt_properties_set_double( b_props, "consumer_scale", mlt_properties_get_double( a_props, "consumer_scale" ) );
// Honour the reverse here
mix = reverse ? 1 - mix : mix;
if ( luma_width > 0 && luma_height > 0 && luma_bitmap != NULL )
// Composite the frames using a luma map
luma_composite( this, b_frame, luma_width, luma_height, luma_bitmap, mix, frame_delta,
- luma_softness, progressive > 0 ? -1 : top_field_first, width, height );
+ luma_softness, progressive ? -1 : top_field_first, width, height );
else
// Dissolve the frames using the time offset for mix value
frame_composite_yuv( this, b_frame, 0, 0, mix, width, height );