bug fixes
[melted] / src / modules / gtk2 / filter_rescale.c
index cf0905e..39185be 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
+
 /** Do it :-).
 */
 
@@ -44,9 +45,11 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        int owidth = *width;
        int oheight = *height;
        uint8_t *input = NULL;
-       
        char *interps = mlt_properties_get( properties, "rescale.interp" );
        int interp = PIXOPS_INTERP_BILINEAR;
+       double i_aspect_ratio = mlt_frame_get_aspect_ratio( this );
+       double o_aspect_ratio = mlt_properties_get_double( properties, "consumer_aspect_ratio" );
+       
        if ( strcmp( interps, "nearest" ) == 0 )
                interp = PIXOPS_INTERP_NEAREST;
        else if ( strcmp( interps, "tiles" ) == 0 )
@@ -54,15 +57,34 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        else if ( strcmp( interps, "hyper" ) == 0 )
                interp = PIXOPS_INTERP_HYPER;
 
-       mlt_frame_get_image( this, &input, format, &iwidth, &iheight, 0 );
+       mlt_frame_get_image( this, &input, format, &iwidth, &iheight, writable );
+
+       if ( o_aspect_ratio != 0 && o_aspect_ratio != i_aspect_ratio && mlt_properties_get( properties, "distort" ) == NULL )
+       {
+               int temp_width = i_aspect_ratio / o_aspect_ratio * owidth + 0.5;
+
+               // Determine maximum size within the aspect ratio:
+               if ( temp_width > owidth )
+                       if ( i_aspect_ratio > o_aspect_ratio )
+                               oheight = o_aspect_ratio / i_aspect_ratio * oheight + 0.5;
+                       else
+                               oheight = i_aspect_ratio / o_aspect_ratio * oheight + 0.5;
+               else
+                       owidth = temp_width;
+                       
+               // Tell frame we have conformed the aspect to the consumer
+               mlt_frame_set_aspect_ratio( this, o_aspect_ratio );
+       }
+       //fprintf( stderr, "rescale: from %dx%d (aspect %f) to %dx%d (aspect %f)\n", iwidth, iheight, i_aspect_ratio, owidth, oheight, o_aspect_ratio );
 
-       // If width and height are correct, don't do anything
-       if ( 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 );
+                       // IRRIGATE ME
+                       uint8_t *output = malloc( owidth * ( oheight + 1 ) * 2 );
 
                        // Calculate strides
                        int istride = iwidth * 2;
@@ -71,7 +93,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                        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, free, NULL );
                        mlt_properties_set_int( properties, "width", owidth );
                        mlt_properties_set_int( properties, "height", oheight );
 
@@ -81,31 +103,85 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                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
+                       // IRRIGATE ME
+                       uint8_t *output = malloc( 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
+                                       // IRRIGATE ME
+                                       uint8_t *alpha = malloc( 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 ), free, 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
+                                       // IRRIGATE ME
+                                       uint8_t *alpha = malloc( 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 ), free, 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, free, 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;
@@ -113,6 +189,15 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        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.
 */
 
@@ -121,6 +206,9 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
        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;
 }