]> git.sesse.net Git - mlt/blobdiff - src/modules/avformat/filter_swscale.c
Add service locks for parallelism.
[mlt] / src / modules / avformat / filter_swscale.c
index d1266aeaeed5c97d5285d915ef685ce75855a3a0..990be78786b6c9fe98c88b212eeef4ae372f7628 100644 (file)
 #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;
@@ -56,7 +46,8 @@ static inline int convert_mlt_to_av_cs( mlt_image_format format )
                        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;
@@ -64,7 +55,6 @@ static inline int convert_mlt_to_av_cs( mlt_image_format format )
                case mlt_image_yuv420p:
                        value = PIX_FMT_YUV420P;
                        break;
-               case mlt_image_opengl:
                case mlt_image_none:
                        fprintf( stderr, "Invalid format...\n" );
                        break;
@@ -73,7 +63,7 @@ static inline int convert_mlt_to_av_cs( mlt_image_format format )
        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 this, 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 );
@@ -101,75 +91,98 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iform
                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 );
+       // Determine the bytes per pixel
+       int bpp;
+       switch ( *format )
+       {
+               case mlt_image_yuv422:
+                       bpp = 2;
+                       interp |= SWS_FULL_CHR_H_INP;
+                       break;
+               case mlt_image_rgb24:
+                       bpp = 3;
+                       interp |= SWS_FULL_CHR_H_INT;
+                       break;
+               case mlt_image_rgb24a:
+               case mlt_image_opengl:
+                       bpp = 4;
+                       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
 
        // Convert the pixel formats
-       iformat = convert_mlt_to_av_cs( iformat );
-       oformat = convert_mlt_to_av_cs( oformat );
+       int avformat = convert_mlt_to_av_cs( *format );
 
-       avpicture_fill( &input, *image, iformat, iwidth, iheight );
-       avpicture_fill( &output, outbuf, oformat, owidth, oheight );
+       // 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 );
 
-       // Extract the alpha channel
-       if ( iformat == PIX_FMT_RGB32 && oformat == PIX_FMT_YUYV422 )
+       // 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 )
        {
-               // 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 );
-               }
+               owidth = owidth > 2048 ? 2048 : owidth;
+               context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
        }
-
-       // 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 );
-
-       // 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 ) )
+       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, 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 ) * bpp, ( 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.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( this );
+                       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, 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 );
+                       }
                }
+       
+               return 0;
+       }
+       else
+       {
+               return 1;
        }
-
-       return 0;
 }
 
 /** Constructor for the filter.
@@ -177,9 +190,20 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iform
 
 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 this = mlt_factory_filter( profile, "rescale", NULL );
+       
        // If successful, then initialise it
        if ( this != NULL )
        {
@@ -187,7 +211,7 @@ mlt_filter filter_swscale_init( mlt_profile profile, void *arg )
                mlt_properties properties = MLT_FILTER_PROPERTIES( this );
 
                // 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 );