#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+
/** Do it :-).
*/
*width = 720;
if ( *height == 0 )
*height = 576;
+ if ( *width < 2 || *height < 6 )
+ return 1;
mlt_properties properties = mlt_frame_properties( this );
int iwidth = *width;
int owidth = *width;
int oheight = *height;
uint8_t *input = NULL;
-
char *interps = mlt_properties_get( properties, "rescale.interp" );
int interp = PIXOPS_INTERP_BILINEAR;
+
if ( strcmp( interps, "nearest" ) == 0 )
interp = PIXOPS_INTERP_NEAREST;
else if ( strcmp( interps, "tiles" ) == 0 )
else if ( strcmp( interps, "hyper" ) == 0 )
interp = PIXOPS_INTERP_HYPER;
- mlt_frame_get_image( this, &input, format, &iwidth, &iheight, 0 );
-
-#if 0
- // Determine maximum size within the aspect ratio:
- double aspect_ratio = mlt_frame_get_aspect_ratio( this );
- // TODO: these need to be provided
- double dsar = oheight < 576 ? (8.0 / 9.0) : (48.0 / 45.0);
- double ssar = iheight < 576 ? (8.0 / 9.0) : (48.0 / 45.0);
+ // If real_width/height exist, we want that as minimum information
+ if ( mlt_properties_get_int( properties, "real_width" ) )
+ {
+ iwidth = mlt_properties_get_int( properties, "real_width" );
+ iheight = mlt_properties_get_int( properties, "real_height" );
+ }
- if ( ( (double) owidth * dsar / iwidth * ssar ) < ( (double) oheight / iheight ) )
- oheight = (double) owidth * dsar / aspect_ratio;
- else
- owidth = (int)( ( aspect_ratio * oheight / dsar ) + 0.5 ) >> 1 << 1;
+ // Let the producer know what we are actually requested to obtain
+ mlt_properties_set_int( properties, "rescale_width", *width );
+ mlt_properties_set_int( properties, "rescale_height", *height );
- fprintf( stderr, "rescale: from %dx%d (%f) to %dx%d\n", iwidth, iheight, aspect_ratio, owidth, oheight );
-#endif
+ // Get the image as requested
+ mlt_frame_get_image( this, &input, format, &iwidth, &iheight, writable );
- // If width and height are correct, don't do anything
- if ( input != NULL && ( iwidth != owidth || iheight != oheight ) )
+ if ( input != NULL )
{
- if ( *format == mlt_image_yuv422 )
+ // If width and height are correct, don't do anything
+ if ( *format == mlt_image_yuv422 && strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) )
{
// Create the output image
- uint8_t *output = malloc( owidth * oheight * 2 );
+ uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
// Calculate strides
int istride = iwidth * 2;
yuv422_scale_simple( output, owidth, oheight, ostride, input, iwidth, iheight, istride, interp );
// Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * oheight * 2, free, NULL );
+ mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
mlt_properties_set_int( properties, "width", owidth );
mlt_properties_set_int( properties, "height", oheight );
// Return the output
*image = output;
}
+ else if ( *format == mlt_image_yuv422 && !strcmp( interps, "none" ) )
+ {
+ // Do nothing
+ *width = iwidth;
+ *height = iheight;
+ *image = input;
+ }
else if ( *format == mlt_image_rgb24 || *format == mlt_image_rgb24a )
{
int bpp = (*format == mlt_image_rgb24a ? 4 : 3 );
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( input, GDK_COLORSPACE_RGB,
- (*format == mlt_image_rgb24a), 24, iwidth, iheight,
- iwidth * bpp, NULL, NULL );
- GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf, owidth, oheight, interp );
-
- // Create the output image
- uint8_t *output = malloc( owidth * oheight * bpp );
-
- int i;
- for ( i = 0; i < oheight; i++ )
- memcpy( output + i * owidth * bpp,
- gdk_pixbuf_get_pixels( scaled ) + i * gdk_pixbuf_get_rowstride( scaled ),
- gdk_pixbuf_get_width( scaled ) * bpp );
-
- g_object_unref( pixbuf );
- g_object_unref( scaled );
+ // Create the yuv image
+ uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
+
+ if ( strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) )
+ {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( input, GDK_COLORSPACE_RGB,
+ ( *format == mlt_image_rgb24a ), 8, iwidth, iheight,
+ iwidth * bpp, NULL, NULL );
+
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf, owidth, oheight, interp );
+ g_object_unref( pixbuf );
+
+ // Extract YUV422 and alpha
+ if ( bpp == 4 )
+ {
+ // Allocate the alpha mask
+ uint8_t *alpha = mlt_pool_alloc( owidth * ( oheight + 1 ) );
+
+ // Convert the image and extract alpha
+ mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( scaled ),
+ owidth, oheight,
+ gdk_pixbuf_get_rowstride( scaled ),
+ output, alpha );
+
+ mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
+ }
+ else
+ {
+ // No alpha to extract
+ mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( scaled ),
+ owidth, oheight,
+ gdk_pixbuf_get_rowstride( scaled ),
+ output );
+ }
+ g_object_unref( scaled );
+ }
+ else
+ {
+ // Extract YUV422 and alpha
+ if ( bpp == 4 )
+ {
+ // Allocate the alpha mask
+ uint8_t *alpha = mlt_pool_alloc( owidth * ( oheight + 1 ) );
+
+ // Convert the image and extract alpha
+ mlt_convert_rgb24a_to_yuv422( input,
+ owidth, oheight,
+ owidth * 4,
+ output, alpha );
+
+ mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
+ }
+ else
+ {
+ // No alpha to extract
+ mlt_convert_rgb24_to_yuv422( input,
+ owidth, oheight,
+ owidth * 3,
+ output );
+ }
+ }
+
// Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * oheight * bpp, free, NULL );
+ mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
mlt_properties_set_int( properties, "width", owidth );
mlt_properties_set_int( properties, "height", oheight );
// Return the output
+ *format = mlt_image_yuv422;
+ *width = owidth;
+ *height = oheight;
*image = output;
}
+ else
+ *image = input;
}
else
*image = input;
return 0;
}
+static uint8_t *producer_get_alpha_mask( mlt_frame this )
+{
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( this );
+
+ // Return the alpha mask
+ return mlt_properties_get_data( properties, "alpha", NULL );
+}
+
/** Filter processing.
*/
mlt_frame_push_get_image( frame, filter_get_image );
mlt_properties_set( mlt_frame_properties( frame ), "rescale.interp",
mlt_properties_get( mlt_filter_properties( this ), "interpolation" ) );
+
+ // Set alpha call back
+ frame->get_alpha_mask = producer_get_alpha_mask;
return frame;
}
mlt_filter filter_rescale_init( char *arg )
{
- mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
- if ( mlt_filter_init( this, this ) == 0 )
+ mlt_filter this = mlt_filter_new( );
+ if ( this != NULL )
{
this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set( mlt_filter_properties( this ), "interpolation", arg );
- else
- mlt_properties_set( mlt_filter_properties( this ), "interpolation", "bilinear" );
+ mlt_properties_set( mlt_filter_properties( this ), "interpolation", arg == NULL ? "bilinear" : arg );
}
return this;
}
-