#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
#include <framework/mlt_factory.h>
-#include <framework/mlt_factory.h>
// ffmpeg Header files
-#include <avformat.h>
-#include <swscale.h>
+#include <libavformat/avformat.h>
+#include <libswscale/swscale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#if LIBAVUTIL_VERSION_INT < (50<<16)
#define PIX_FMT_RGB32 PIX_FMT_RGBA32
#define PIX_FMT_YUYV422 PIX_FMT_YUV422
#endif
-static inline int is_big_endian( )
-{
- union { int i; char c[ 4 ]; } big_endian_test;
- big_endian_test.i = 1;
-
- return big_endian_test.c[ 0 ] != 1;
-}
-
static inline int convert_mlt_to_av_cs( mlt_image_format format )
{
int value = 0;
value = PIX_FMT_RGB24;
break;
case mlt_image_rgb24a:
- value = PIX_FMT_RGB32;
+ case mlt_image_opengl:
+ value = PIX_FMT_RGBA;
break;
case mlt_image_yuv422:
value = PIX_FMT_YUYV422;
case mlt_image_yuv420p:
value = PIX_FMT_YUV420P;
break;
- case mlt_image_opengl:
- case mlt_image_none:
+ default:
fprintf( stderr, "Invalid format...\n" );
break;
}
return value;
}
-static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iformat, mlt_image_format oformat, int iwidth, int iheight, int owidth, int oheight )
+static int filter_scale( mlt_frame frame, uint8_t **image, mlt_image_format *format, int iwidth, int iheight, int owidth, int oheight )
{
// Get the properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
+ mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
// Get the requested interpolation method
char *interps = mlt_properties_get( properties, "rescale.interp" );
interp = SWS_LANCZOS;
else if ( strcmp( interps, "spline" ) == 0 )
interp = SWS_SPLINE;
+ interp |= SWS_ACCURATE_RND;
- AVPicture input;
- AVPicture output;
- uint8_t *outbuf = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
-
- // Convert the pixel formats
- iformat = convert_mlt_to_av_cs( iformat );
- oformat = convert_mlt_to_av_cs( oformat );
+ // Determine the bytes per pixel
+ int bpp;
+ mlt_image_format_size( *format, 0, 0, &bpp );
- avpicture_fill( &input, *image, iformat, iwidth, iheight );
- avpicture_fill( &output, outbuf, oformat, owidth, oheight );
-
- // Extract the alpha channel
- if ( iformat == PIX_FMT_RGB32 && oformat == PIX_FMT_YUYV422 )
+ // Set swscale flags to get good quality
+ switch ( *format )
{
- // Allocate the alpha mask
- uint8_t *alpha = mlt_pool_alloc( iwidth * ( iheight + 1 ) );
- if ( alpha )
- {
- // Convert the image and extract alpha
- mlt_convert_rgb24a_to_yuv422( *image, iwidth, iheight, iwidth * 4, outbuf, alpha );
- mlt_properties_set_data( properties, "alpha", alpha, iwidth * ( iheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
- iformat = PIX_FMT_YUYV422;
- avpicture_fill( &input, outbuf, iformat, iwidth, iheight );
- avpicture_fill( &output, *image, oformat, owidth, oheight );
- }
+ case mlt_image_yuv422:
+ interp |= SWS_FULL_CHR_H_INP;
+ break;
+ case mlt_image_rgb24:
+ interp |= SWS_FULL_CHR_H_INT;
+ break;
+ case mlt_image_rgb24a:
+ case mlt_image_opengl:
+ interp |= SWS_FULL_CHR_H_INT;
+ break;
+ default:
+ // XXX: we only know how to rescale packed formats
+ return 1;
}
+#ifdef USE_MMX
+ interp |= SWS_CPU_CAPS_MMX;
+#endif
+#ifdef USE_SSE
+ interp |= SWS_CPU_CAPS_MMX2;
+#endif
- // Create the context and output image
- struct SwsContext *context = sws_getContext( iwidth, iheight, iformat, owidth, oheight, oformat, interp, NULL, NULL, NULL);
- assert(context);
-
- // Perform the scaling
- sws_scale( context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
- sws_freeContext( context );
-
- // Now update the frame
- mlt_properties_set_data( properties, "image", output.data[0], owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
+ // Convert the pixel formats
+ int avformat = convert_mlt_to_av_cs( *format );
- // Return the output
- *image = output.data[0];
+ // Fill out the AVPictures
+ AVPicture input;
+ AVPicture output;
+ uint8_t *outbuf = mlt_pool_alloc( owidth * ( oheight + 1 ) * bpp );
+ avpicture_fill( &input, *image, avformat, iwidth, iheight );
+ avpicture_fill( &output, outbuf, avformat, owidth, oheight );
- // Scale the alpha channel only if exists and not correct size
- int alpha_size = 0;
- mlt_properties_get_data( properties, "alpha", &alpha_size );
- if ( alpha_size > 0 && alpha_size != ( owidth * oheight ) )
+ // Create the context and output image
+ owidth = owidth > 5120 ? 5120 : owidth;
+ struct SwsContext *context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
+ if ( !context )
+ {
+ owidth = owidth > 2048 ? 2048 : owidth;
+ context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
+ }
+ if ( context )
{
- // Create the context and output image
- uint8_t *alpha = mlt_frame_get_alpha_mask( this );
- if ( alpha )
+ // Perform the scaling
+ sws_scale( context, (const uint8_t* const*) input.data, input.linesize, 0, iheight, output.data, output.linesize);
+ sws_freeContext( context );
+
+ // Now update the frame
+ mlt_frame_set_image( frame, output.data[0], owidth * ( oheight + 1 ) * bpp, mlt_pool_release );
+
+ // Return the output
+ *image = output.data[0];
+
+ // Scale the alpha channel only if exists and not correct size
+ int alpha_size = 0;
+ mlt_properties_get_data( properties, "alpha", &alpha_size );
+ if ( alpha_size > 0 && alpha_size != ( owidth * oheight ) )
{
- iformat = oformat = PIX_FMT_GRAY8;
- struct SwsContext *context = sws_getContext( iwidth, iheight, iformat, owidth, oheight, oformat, interp, NULL, NULL, NULL);
- avpicture_fill( &input, alpha, iformat, iwidth, iheight );
- outbuf = mlt_pool_alloc( owidth * oheight );
- avpicture_fill( &output, outbuf, oformat, owidth, oheight );
-
- // Perform the scaling
- sws_scale( context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
- sws_freeContext( context );
-
- // Set it back on the frame
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "alpha", output.data[0], owidth * oheight, mlt_pool_release, NULL );
+ // Create the context and output image
+ uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
+ if ( alpha )
+ {
+ avformat = PIX_FMT_GRAY8;
+ struct SwsContext *context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
+ avpicture_fill( &input, alpha, avformat, iwidth, iheight );
+ outbuf = mlt_pool_alloc( owidth * oheight );
+ avpicture_fill( &output, outbuf, avformat, owidth, oheight );
+
+ // Perform the scaling
+ sws_scale( context, (const uint8_t* const*) input.data, input.linesize, 0, iheight, output.data, output.linesize);
+ sws_freeContext( context );
+
+ // Set it back on the frame
+ mlt_frame_set_alpha( frame, output.data[0], owidth * oheight, mlt_pool_release );
+ }
}
+
+ return 0;
+ }
+ else
+ {
+ return 1;
}
-
- return 0;
}
/** Constructor for the filter.
mlt_filter filter_swscale_init( mlt_profile profile, void *arg )
{
- // Create a new scaler
- mlt_filter this = mlt_factory_filter( profile, "rescale", arg );
+ // Test to see if swscale accepts the arg as resolution
+ if ( arg )
+ {
+ int width = (int) arg;
+ struct SwsContext *context = sws_getContext( width, width, PIX_FMT_RGB32, 64, 64, PIX_FMT_RGB32, SWS_BILINEAR, NULL, NULL, NULL);
+ if ( context )
+ sws_freeContext( context );
+ else
+ return NULL;
+ }
+ // Create a new scaler
+ mlt_filter filter = mlt_factory_filter( profile, "rescale", NULL );
+
// If successful, then initialise it
- if ( this != NULL )
+ if ( filter != NULL )
{
// Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
+ mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
// Set the inerpolation
- mlt_properties_set( properties, "interpolation", arg == NULL ? "bilinear" : arg );
+ mlt_properties_set( properties, "interpolation", "bilinear" );
// Set the method
mlt_properties_set_data( properties, "method", filter_scale, 0, NULL, NULL );
}
- return this;
+ return filter;
}