From 2657693db7ce32ddb0a48b677e4cec6101a35e20 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Fri, 3 Jul 2009 14:55:15 -0700 Subject: [PATCH] Massive refactoring of image conversion. This drops all image color space and pixel format conversions from the mlt_frame class. Instead, it adds a convert_image virtual function to the mlt_frame class that is called within mlt_frame_get_image(). The newly added imageconvert filter sets that virtual function and contains the various conversion routines. The loader producer automatically attaches this filter to the producer it creates. Signed-off-by: Dan Dennedy --- configure | 4 +- docs/policies.txt | 7 + src/framework/mlt.h | 4 +- src/framework/mlt_frame.c | 623 +------------------ src/framework/mlt_frame.h | 12 +- src/framework/mlt_log.c | 12 +- src/modules/avformat/filter_avcolour_space.c | 171 +++-- src/modules/avformat/filter_avdeinterlace.c | 10 +- src/modules/avformat/filter_swscale.c | 72 +-- src/modules/avformat/producer_avformat.c | 26 +- src/modules/core/Makefile | 1 + src/modules/core/factory.c | 2 + src/modules/core/filter_brightness.c | 3 +- src/modules/core/filter_crop.c | 14 +- src/modules/core/filter_gamma.c | 3 +- src/modules/core/filter_greyscale.c | 3 +- src/modules/core/filter_imageconvert.c | 469 ++++++++++++++ src/modules/core/filter_luma.c | 1 + src/modules/core/filter_mirror.c | 3 +- src/modules/core/filter_obscure.c | 3 +- src/modules/core/filter_rescale.c | 191 +++--- src/modules/core/filter_resize.c | 169 ++++- src/modules/core/filter_watermark.c | 1 + src/modules/core/loader.ini | 6 + src/modules/core/producer_colour.c | 132 ++-- src/modules/core/producer_consumer.c | 3 +- src/modules/core/producer_ppm.c | 20 +- src/modules/core/transition_luma.c | 14 +- src/modules/effectv/filter_burn.c | 15 +- src/modules/frei0r/filter_frei0r.c | 13 +- src/modules/frei0r/frei0r_helper.c | 36 +- src/modules/frei0r/frei0r_helper.h | 3 +- src/modules/frei0r/producer_frei0r.c | 6 +- src/modules/frei0r/transition_frei0r.c | 11 +- src/modules/gtk2/filter_rescale.c | 85 ++- src/modules/gtk2/producer_pango.c | 108 +--- src/modules/gtk2/producer_pixbuf.c | 136 ++-- src/modules/kdenlive/filter_boxblur.c | 5 +- src/modules/kdenlive/filter_wave.c | 22 +- src/modules/kdenlive/producer_framebuffer.c | 5 +- src/modules/motion_est/filter_crop_detect.c | 14 +- src/modules/motion_est/filter_motion_est.c | 14 +- src/modules/motion_est/filter_vismv.c | 1 + src/modules/motion_est/producer_slowmotion.c | 15 +- src/modules/oldfilm/filter_dust.c | 5 +- src/modules/oldfilm/filter_grain.c | 3 +- src/modules/oldfilm/filter_lines.c | 3 +- src/modules/oldfilm/filter_oldfilm.c | 3 +- src/modules/oldfilm/filter_tcolor.c | 3 +- src/modules/oldfilm/filter_vignette.c | 3 +- src/modules/plus/filter_affine.c | 6 +- src/modules/plus/filter_charcoal.c | 3 +- src/modules/plus/filter_invert.c | 3 +- src/modules/plus/filter_sepia.c | 3 +- src/modules/plus/transition_affine.c | 1 + src/modules/qimage/producer_qimage.c | 71 +-- src/modules/qimage/qimage_wrapper.cpp | 83 ++- src/modules/qimage/qimage_wrapper.h | 3 +- src/modules/sdl/consumer_sdl.c | 15 - src/modules/sdl/consumer_sdl_still.c | 47 +- src/modules/sdl/producer_sdl_image.c | 22 +- src/modules/vmfx/filter_chroma.c | 1 + src/modules/vmfx/filter_chroma_hold.c | 1 + src/modules/vmfx/filter_mono.c | 1 + src/modules/vmfx/filter_shape.c | 1 + src/modules/xine/filter_deinterlace.c | 11 +- 66 files changed, 1308 insertions(+), 1452 deletions(-) create mode 100644 src/modules/core/filter_imageconvert.c diff --git a/configure b/configure index 0ce1fb8f..3315473c 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #!/bin/sh -export version=0.4.4 -export soversion=1 +export version=0.4.5 +export soversion=2 show_help() { diff --git a/docs/policies.txt b/docs/policies.txt index 470bf6e0..60ba1db5 100644 --- a/docs/policies.txt +++ b/docs/policies.txt @@ -50,6 +50,13 @@ copyright the MLT integration code as your own. However, if you have heavily modified the original code beyond nearly all recognition, you can copyright it as your own and attribute the original author as inspiration. +A producer should validate its input and return NULL on failure. + +A filter or transition should express the image format it wants before calling +mlt_frame_get_image(). It should expect to receive what it requested as long +as it is yuv422, rgb24, or rgb24a and you are using the imageconvert filter +(typically via the loader producer and its loader.ini file). + Bug Reporting: First preference is to use the SourceForge tracker: http://sourceforge.net/tracker/?group_id=96039&atid=613414 diff --git a/src/framework/mlt.h b/src/framework/mlt.h index e073fbc9..bad3688c 100644 --- a/src/framework/mlt.h +++ b/src/framework/mlt.h @@ -23,8 +23,8 @@ #ifndef _MLT_H_ #define _MLT_H_ -#define LIBMLT_VERSION_INT ((0<<16)+(4<<8)+4) -#define LIBMLT_VERSION 0.4.4 +#define LIBMLT_VERSION_INT ((0<<16)+(4<<8)+5) +#define LIBMLT_VERSION 0.4.5 #ifdef __cplusplus extern "C" diff --git a/src/framework/mlt_frame.c b/src/framework/mlt_frame.c index 0899b065..6bd5442c 100644 --- a/src/framework/mlt_frame.c +++ b/src/framework/mlt_frame.c @@ -25,6 +25,7 @@ #include "mlt_producer.h" #include "mlt_factory.h" #include "mlt_profile.h" +#include "mlt_log.h" #include #include @@ -244,6 +245,20 @@ void mlt_frame_replace_image( mlt_frame this, uint8_t *image, mlt_image_format f this->get_alpha_mask = NULL; } +const char * mlt_image_format_name( mlt_image_format format ) +{ + switch ( format ) + { + case mlt_image_none: return "none"; + case mlt_image_rgb24: return "rgb24"; + case mlt_image_rgb24a: return "rgb24a"; + case mlt_image_yuv422: return "yuv422"; + case mlt_image_yuv420p: return "yuv420p"; + case mlt_image_opengl: return "opengl"; + } + return "invalid"; +} + /** Get the image associated to the frame. */ @@ -252,41 +267,46 @@ int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *for mlt_properties properties = MLT_FRAME_PROPERTIES( this ); mlt_get_image get_image = mlt_frame_pop_get_image( this ); mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL ); + mlt_image_format requested_format = *format; int error = 0; - if ( get_image != NULL ) + if ( get_image ) { mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 ); mlt_position position = mlt_frame_get_position( this ); - error = get_image( this, buffer, format, width, height, writable ); + error = get_image( this, buffer, format, width, height, writable ); mlt_properties_set_int( properties, "width", *width ); mlt_properties_set_int( properties, "height", *height ); mlt_properties_set_int( properties, "format", *format ); mlt_frame_set_position( this, position ); + if ( this->convert_image ) + this->convert_image( this, buffer, format, requested_format ); } - else if ( mlt_properties_get_data( properties, "image", NULL ) != NULL ) + else if ( mlt_properties_get_data( properties, "image", NULL ) ) { *format = mlt_properties_get_int( properties, "format" ); *buffer = mlt_properties_get_data( properties, "image", NULL ); *width = mlt_properties_get_int( properties, "width" ); *height = mlt_properties_get_int( properties, "height" ); + if ( this->convert_image ) + this->convert_image( this, buffer, format, requested_format ); } - else if ( producer != NULL ) + else if ( producer ) { mlt_frame test_frame = NULL; mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 ); - if ( test_frame != NULL ) + if ( test_frame ) { mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame ); mlt_properties_set_double( test_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "consumer_aspect_ratio" ) ); mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) ); mlt_frame_get_image( test_frame, buffer, format, width, height, writable ); mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); - mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL ); - mlt_properties_set_int( properties, "width", *width ); - mlt_properties_set_int( properties, "height", *height ); - mlt_properties_set_int( properties, "format", *format ); mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) ); +// mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL ); +// mlt_properties_set_int( properties, "width", *width ); +// mlt_properties_set_int( properties, "height", *height ); +// mlt_properties_set_int( properties, "format", *format ); } else { @@ -519,591 +539,6 @@ void mlt_frame_close( mlt_frame this ) /***** convenience functions *****/ -int mlt_convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total ) -{ - int ret = 0; - int yy, uu, vv; - int r,g,b; - total /= 2; - while (total--) - { - yy = yuv[0]; - uu = yuv[1]; - vv = yuv[3]; - YUV2RGB(yy, uu, vv, r, g, b); - rgba[0] = r; - rgba[1] = g; - rgba[2] = b; - rgba[3] = 255; - yy = yuv[2]; - YUV2RGB(yy, uu, vv, r, g, b); - rgba[4] = r; - rgba[5] = g; - rgba[6] = b; - rgba[7] = 255; - yuv += 4; - rgba += 8; - } - return ret; -} - -int mlt_convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha ) -{ - int ret = 0; - register int y0, y1, u0, u1, v0, v1; - register int r, g, b; - register uint8_t *d = yuv; - register int i, j; - - if ( alpha ) - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgba + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - r = *s++; - g = *s++; - b = *s++; - *alpha++ = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - r = *s++; - g = *s++; - b = *s++; - *alpha++ = *s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - r = *s++; - g = *s++; - b = *s++; - *alpha++ = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - else - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgba + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - r = *s++; - g = *s++; - b = *s++; - s++; - RGB2YUV (r, g, b, y0, u0 , v0); - r = *s++; - g = *s++; - b = *s++; - s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - r = *s++; - g = *s++; - b = *s++; - s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - - return ret; -} - -int mlt_convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv ) -{ - int ret = 0; - register int y0, y1, u0, u1, v0, v1; - register int r, g, b; - register uint8_t *d = yuv; - register int i, j; - - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgb + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - return ret; -} - -int mlt_convert_bgr24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha ) -{ - int ret = 0; - register int y0, y1, u0, u1, v0, v1; - register int r, g, b; - register uint8_t *d = yuv; - register int i, j; - - if ( alpha ) - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgba + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - b = *s++; - g = *s++; - r = *s++; - *alpha++ = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - b = *s++; - g = *s++; - r = *s++; - *alpha++ = *s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - b = *s++; - g = *s++; - r = *s++; - *alpha++ = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - else - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgba + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - b = *s++; - g = *s++; - r = *s++; - s++; - RGB2YUV (r, g, b, y0, u0 , v0); - b = *s++; - g = *s++; - r = *s++; - s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - b = *s++; - g = *s++; - r = *s++; - s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - return ret; -} - -int mlt_convert_bgr24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv ) -{ - int ret = 0; - register int y0, y1, u0, u1, v0, v1; - register int r, g, b; - register uint8_t *d = yuv; - register int i, j; - - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgb + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - b = *s++; - g = *s++; - r = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - b = *s++; - g = *s++; - r = *s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - b = *s++; - g = *s++; - r = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - return ret; -} - -int mlt_convert_argb_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha ) -{ - int ret = 0; - register int y0, y1, u0, u1, v0, v1; - register int r, g, b; - register uint8_t *d = yuv; - register int i, j; - - if ( alpha ) - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgba + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - *alpha++ = *s++; - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *alpha++ = *s++; - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - *alpha++ = *s++; - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - else - for ( i = 0; i < height; i++ ) - { - register uint8_t *s = rgba + ( stride * i ); - for ( j = 0; j < ( width / 2 ); j++ ) - { - s++; - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - s++; - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y1, u1 , v1); - *d++ = y0; - *d++ = (u0+u1) >> 1; - *d++ = y1; - *d++ = (v0+v1) >> 1; - } - if ( width % 2 ) - { - s++; - r = *s++; - g = *s++; - b = *s++; - RGB2YUV (r, g, b, y0, u0 , v0); - *d++ = y0; - *d++ = u0; - } - } - return ret; -} - -int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int stride, uint8_t *yuv ) -{ - int ret = 0; - register int i, j; - - int half = width >> 1; - - uint8_t *Y = yuv420p; - uint8_t *U = Y + width * height; - uint8_t *V = U + width * height / 4; - - register uint8_t *d = yuv; - - for ( i = 0; i < height; i++ ) - { - register uint8_t *u = U + ( i / 2 ) * ( half ); - register uint8_t *v = V + ( i / 2 ) * ( half ); - - for ( j = 0; j < half; j++ ) - { - *d ++ = *Y ++; - *d ++ = *u ++; - *d ++ = *Y ++; - *d ++ = *v ++; - } - } - return ret; -} - -uint8_t *mlt_resize_alpha( uint8_t *input, int owidth, int oheight, int iwidth, int iheight, uint8_t alpha_value ) -{ - uint8_t *output = NULL; - - if ( input != NULL && ( iwidth != owidth || iheight != oheight ) && ( owidth > 6 && oheight > 6 ) ) - { - uint8_t *out_line; - int offset_x = ( owidth - iwidth ) / 2; - int offset_y = ( oheight - iheight ) / 2; - int iused = iwidth; - - output = mlt_pool_alloc( owidth * oheight ); - memset( output, alpha_value, owidth * oheight ); - - offset_x -= offset_x % 2; - - out_line = output + offset_y * owidth; - out_line += offset_x; - - // Loop for the entirety of our output height. - while ( iheight -- ) - { - // We're in the input range for this row. - memcpy( out_line, input, iused ); - - // Move to next input line - input += iwidth; - - // Move to next output line - out_line += owidth; - } - } - - return output; -} - -void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight ) -{ - // Calculate strides - int istride = iwidth * 2; - int ostride = owidth * 2; - int offset_x = ( owidth - iwidth ); - int offset_y = ( oheight - iheight ) / 2; - uint8_t *in_line = input; - uint8_t *out_line; - int size = owidth * oheight; - uint8_t *p = output; - - // Optimisation point - if ( output == NULL || input == NULL || ( owidth <= 6 || oheight <= 6 || iwidth <= 6 || oheight <= 6 ) ) - { - return; - } - else if ( iwidth == owidth && iheight == oheight ) - { - memcpy( output, input, iheight * istride ); - return; - } - - while( size -- ) - { - *p ++ = 16; - *p ++ = 128; - } - - offset_x -= offset_x % 4; - - out_line = output + offset_y * ostride; - out_line += offset_x; - - // Loop for the entirety of our output height. - while ( iheight -- ) - { - // We're in the input range for this row. - memcpy( out_line, in_line, iwidth * 2 ); - - // Move to next input line - in_line += istride; - - // Move to next output line - out_line += ostride; - } -} - -/** A resizing function for yuv422 frames - this does not rescale, but simply - resizes. It assumes yuv422 images available on the frame so use with care. -*/ - -uint8_t *mlt_frame_resize_yuv422( mlt_frame this, int owidth, int oheight ) -{ - // Get properties - mlt_properties properties = MLT_FRAME_PROPERTIES( this ); - - // Get the input image, width and height - uint8_t *input = mlt_properties_get_data( properties, "image", NULL ); - uint8_t *alpha = mlt_frame_get_alpha_mask( this ); - - int iwidth = mlt_properties_get_int( properties, "width" ); - int iheight = mlt_properties_get_int( properties, "height" ); - - // If width and height are correct, don't do anything - if ( iwidth != owidth || iheight != oheight ) - { - uint8_t alpha_value = mlt_properties_get_int( properties, "resize_alpha" ); - - // Create the output image - uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 ); - - // Call the generic resize - mlt_resize_yuv422( output, owidth, oheight, input, iwidth, iheight ); - - // Now update the frame - 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 ); - - // We should resize the alpha too - alpha = mlt_resize_alpha( alpha, owidth, oheight, iwidth, iheight, alpha_value ); - if ( alpha != NULL ) - { - mlt_properties_set_data( properties, "alpha", alpha, owidth * oheight, ( mlt_destructor )mlt_pool_release, NULL ); - this->get_alpha_mask = NULL; - } - - // Return the output - return output; - } - // No change, return input - return input; -} - -/** A rescaling function for yuv422 frames - low quality, and provided for testing - only. It assumes yuv422 images available on the frame so use with care. -*/ - -uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight ) -{ - // Get properties - mlt_properties properties = MLT_FRAME_PROPERTIES( this ); - - // Get the input image, width and height - uint8_t *input = mlt_properties_get_data( properties, "image", NULL ); - int iwidth = mlt_properties_get_int( properties, "width" ); - int iheight = mlt_properties_get_int( properties, "height" ); - - // If width and height are correct, don't do anything - if ( iwidth != owidth || iheight != oheight ) - { - // Create the output image - uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 ); - - // Calculate strides - int istride = iwidth * 2; - int ostride = owidth * 2; - - iwidth = iwidth - ( iwidth % 4 ); - - // Derived coordinates - int dy, dx; - - // Calculate ranges - int out_x_range = owidth / 2; - int out_y_range = oheight / 2; - int in_x_range = iwidth / 2; - int in_y_range = iheight / 2; - - // Output pointers - register uint8_t *out_line = output; - register uint8_t *out_ptr; - - // Calculate a middle pointer - uint8_t *in_middle = input + istride * in_y_range + in_x_range * 2; - uint8_t *in_line; - - // Generate the affine transform scaling values - register int scale_width = ( iwidth << 16 ) / owidth; - register int scale_height = ( iheight << 16 ) / oheight; - register int base = 0; - - int outer = out_x_range * scale_width; - int bottom = out_y_range * scale_height; - - // Loop for the entirety of our output height. - for ( dy = - bottom; dy < bottom; dy += scale_height ) - { - // Start at the beginning of the line - out_ptr = out_line; - - // Pointer to the middle of the input line - in_line = in_middle + ( dy >> 16 ) * istride; - - // Loop for the entirety of our output row. - for ( dx = - outer; dx < outer; dx += scale_width ) - { - base = dx >> 15; - base &= 0xfffffffe; - *out_ptr ++ = *( in_line + base ); - base &= 0xfffffffc; - *out_ptr ++ = *( in_line + base + 1 ); - dx += scale_width; - base = dx >> 15; - base &= 0xfffffffe; - *out_ptr ++ = *( in_line + base ); - base &= 0xfffffffc; - *out_ptr ++ = *( in_line + base + 3 ); - } - - // Move to next output line - out_line += ostride; - } - - // Now update the frame - 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 - return output; - } - - // No change, return input - return input; -} - int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { int ret = 0; diff --git a/src/framework/mlt_frame.h b/src/framework/mlt_frame.h index bd586a74..91aa79f4 100644 --- a/src/framework/mlt_frame.h +++ b/src/framework/mlt_frame.h @@ -59,6 +59,7 @@ struct mlt_frame_s /* Virtual methods */ uint8_t * ( *get_alpha_mask )( mlt_frame self ); + int ( *convert_image )( mlt_frame self, uint8_t **image, mlt_image_format *input, mlt_image_format output ); /* Private properties */ mlt_deque stack_image; @@ -99,20 +100,11 @@ extern mlt_producer mlt_frame_get_original_producer( mlt_frame self ); extern void mlt_frame_close( mlt_frame self ); /* convenience functions */ -extern int mlt_convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total ); -extern int mlt_convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha ); -extern int mlt_convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv ); -extern int mlt_convert_bgr24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha ); -extern int mlt_convert_argb_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha ); -extern int mlt_convert_bgr24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv ); -extern int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int stride, uint8_t *yuv ); -extern uint8_t *mlt_frame_resize_yuv422( mlt_frame self, int owidth, int oheight ); -extern uint8_t *mlt_frame_rescale_yuv422( mlt_frame self, int owidth, int oheight ); -extern void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight ); extern int mlt_frame_mix_audio( mlt_frame self, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ); extern int mlt_frame_combine_audio( mlt_frame self, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ); extern int mlt_sample_calculator( float fps, int frequency, int64_t position ); extern int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position ); +extern const char * mlt_image_format_name( mlt_image_format format ); /** This macro scales rgb into the yuv gamut - y is scaled by 219/255 and uv by 224/255. */ #define RGB2YUV(r, g, b, y, u, v)\ diff --git a/src/framework/mlt_log.c b/src/framework/mlt_log.c index 6fb6233e..568b2d71 100644 --- a/src/framework/mlt_log.c +++ b/src/framework/mlt_log.c @@ -38,11 +38,17 @@ void default_callback( void* ptr, int level, const char* fmt, va_list vl ) if ( print_prefix && properties ) { char *mlt_type = mlt_properties_get( properties, "mlt_type" ); + char *mlt_service = mlt_properties_get( properties, "mlt_service" ); char *resource = mlt_properties_get( properties, "resource" ); - if ( resource && *resource && resource[0] == '<' && resource[ strlen(resource) - 1 ] == '>' ) - mlt_type = resource; - fprintf( stderr, "[%s @ %p]", mlt_type, ptr ); + if ( !( resource && *resource && resource[0] == '<' && resource[ strlen(resource) - 1 ] == '>' ) ) + mlt_type = mlt_properties_get( properties, "mlt_type" ); + if ( mlt_service ) + fprintf( stderr, "[%s %s] ", mlt_type, mlt_service ); + else + fprintf( stderr, "[%s %p] ", mlt_type, ptr ); + if ( resource ) + fprintf( stderr, "%s\n ", resource ); } print_prefix = strstr( fmt, "\n" ) != NULL; vfprintf( stderr, fmt, vl ); diff --git a/src/modules/avformat/filter_avcolour_space.c b/src/modules/avformat/filter_avcolour_space.c index 7ca8e493..1cee5f9c 100644 --- a/src/modules/avformat/filter_avcolour_space.c +++ b/src/modules/avformat/filter_avcolour_space.c @@ -20,6 +20,7 @@ #include #include +#include // ffmpeg Header files #include @@ -28,7 +29,6 @@ #endif #if LIBAVUTIL_VERSION_INT < (50<<16) -#define PIX_FMT_RGB32 PIX_FMT_RGBA32 #define PIX_FMT_YUYV422 PIX_FMT_YUV422 #endif @@ -53,7 +53,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; @@ -61,16 +62,15 @@ 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" ); + mlt_log_error( NULL, "[filter avcolour_space] Invalid format\n" ); break; } return value; } -static inline void convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, int width, int height ) +static inline void av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, int width, int height ) { AVPicture input; AVPicture output; @@ -90,111 +90,110 @@ static inline void convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in /** Do it :-). */ -static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +// static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, mlt_image_format output_format ) { - mlt_filter filter = mlt_frame_pop_service( this ); - mlt_properties properties = MLT_FRAME_PROPERTIES( this ); - int output_format = *format; - mlt_image_format forced = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "forced" ); + mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); + int width = mlt_properties_get_int( properties, "width" ); + int height = mlt_properties_get_int( properties, "height" ); int error = 0; - // Allow this filter to force processing in a colour space other than requested - *format = forced != 0 ? forced : *format; - - error = mlt_frame_get_image( this, image, format, width, height, 0 ); - - if ( error == 0 && *format != output_format && *image != NULL && output_format != mlt_image_opengl ) + if ( *format != output_format ) { - int in_fmt = convert_mlt_to_av_cs( *format ); - int out_fmt = convert_mlt_to_av_cs( output_format ); - int size = avpicture_get_size( out_fmt, *width, *height ); - uint8_t *output = mlt_pool_alloc( size ); - convert_image( output, *image, out_fmt, in_fmt, *width, *height ); - - // Special case for alpha rgb input - if ( *format == mlt_image_rgb24a ) + mlt_log_debug( NULL, "[filter avcolour_space] %s -> %s\n", + mlt_image_format_name( *format ), mlt_image_format_name( output_format ) ); + if ( output_format != mlt_image_opengl ) { - register uint8_t *alpha = mlt_frame_get_alpha_mask( this ); - register int len = *width * *height; - register uint8_t *bits = *image; - register int n = ( len + 7 ) / 8; - - if( !is_big_endian( ) ) - bits += 3; - - // Extract alpha mask from the image using Duff's Device - switch( len % 8 ) - { - case 0: do { *alpha ++ = *bits; bits += 4; - case 7: *alpha ++ = *bits; bits += 4; - case 6: *alpha ++ = *bits; bits += 4; - case 5: *alpha ++ = *bits; bits += 4; - case 4: *alpha ++ = *bits; bits += 4; - case 3: *alpha ++ = *bits; bits += 4; - case 2: *alpha ++ = *bits; bits += 4; - case 1: *alpha ++ = *bits; bits += 4; - } - while( --n ); - } - } - - // Update the output - *image = output; - *format = output_format; - mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL ); - mlt_properties_set_int( properties, "format", output_format ); - - // Special case for alpha rgb output - if ( *format == mlt_image_rgb24a ) - { - // Fetch the alpha - register uint8_t *alpha = mlt_frame_get_alpha_mask( this ); - - if ( alpha != NULL ) + int in_fmt = convert_mlt_to_av_cs( *format ); + int out_fmt = convert_mlt_to_av_cs( output_format ); + int size = avpicture_get_size( out_fmt, width, height ); + uint8_t *output = mlt_pool_alloc( size ); + av_convert_image( output, *image, out_fmt, in_fmt, width, height ); + + // Special case for alpha rgb input + //if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) +if (0) { + register uint8_t *alpha = mlt_frame_get_alpha_mask( frame ); + register int len = width * height; register uint8_t *bits = *image; - register int len = *width * *height; register int n = ( len + 7 ) / 8; - + if( !is_big_endian( ) ) bits += 3; - - // Merge the alpha mask into the RGB image using Duff's Device + + // Extract alpha mask from the image using Duff's Device switch( len % 8 ) { - case 0: do { *bits = *alpha++; bits += 4; - case 7: *bits = *alpha++; bits += 4; - case 6: *bits = *alpha++; bits += 4; - case 5: *bits = *alpha++; bits += 4; - case 4: *bits = *alpha++; bits += 4; - case 3: *bits = *alpha++; bits += 4; - case 2: *bits = *alpha++; bits += 4; - case 1: *bits = *alpha++; bits += 4; + case 0: do { *alpha ++ = *bits; bits += 4; + case 7: *alpha ++ = *bits; bits += 4; + case 6: *alpha ++ = *bits; bits += 4; + case 5: *alpha ++ = *bits; bits += 4; + case 4: *alpha ++ = *bits; bits += 4; + case 3: *alpha ++ = *bits; bits += 4; + case 2: *alpha ++ = *bits; bits += 4; + case 1: *alpha ++ = *bits; bits += 4; } while( --n ); } } + + // Update the output + *image = output; + *format = output_format; + mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL ); + mlt_properties_set_int( properties, "format", output_format ); + + // Special case for alpha rgb output +// if ( output_format == mlt_image_rgb24a ) +if (0) + { + // Fetch the alpha + register uint8_t *alpha = mlt_frame_get_alpha_mask( frame ); + + if ( alpha != NULL ) + { + register uint8_t *bits = *image; + register int len = width * height; + register int n = ( len + 7 ) / 8; + + if( !is_big_endian( ) ) + bits += 3; + + // Merge the alpha mask into the RGB image using Duff's Device + switch( len % 8 ) + { + case 0: do { *bits = *alpha++; bits += 4; + case 7: *bits = *alpha++; bits += 4; + case 6: *bits = *alpha++; bits += 4; + case 5: *bits = *alpha++; bits += 4; + case 4: *bits = *alpha++; bits += 4; + case 3: *bits = *alpha++; bits += 4; + case 2: *bits = *alpha++; bits += 4; + case 1: *bits = *alpha++; bits += 4; + } + while( --n ); + } + } + } } - } - else if ( error == 0 && *format != output_format && *image != NULL && output_format == mlt_image_opengl ) - { - if ( *format == mlt_image_yuv422 ) + else if ( *format == mlt_image_yuv422 ) // && output_format == mlt_image_opengl { - int size = *width * *height * 4; + int size = width * height * 4; uint8_t *output = mlt_pool_alloc( size ); - int h = *height; - int w = *width; + int h = height; + int w = width; uint8_t *o = output + size; int ostride = w * 4; uint8_t *p = *image; - uint8_t *alpha = mlt_frame_get_alpha_mask( this ) + *width * *height; + uint8_t *alpha = mlt_frame_get_alpha_mask( frame ) + width * height; int r, g, b; while( h -- ) { - w = *width; + w = width; o -= ostride; - alpha -= *width; + alpha -= width; while( w >= 2 ) { YUV2RGB( *p, *( p + 1 ), *( p + 3 ), r, g, b ); @@ -211,7 +210,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * p += 4; } o -= ostride; - alpha -= *width; + alpha -= width; } mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL ); @@ -220,7 +219,6 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * *format = output_format; } } - return error; } @@ -229,8 +227,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) { - mlt_frame_push_service( frame, this ); - mlt_frame_push_get_image( frame, filter_get_image ); + frame->convert_image = convert_image; return frame; } diff --git a/src/modules/avformat/filter_avdeinterlace.c b/src/modules/avformat/filter_avdeinterlace.c index d4afa350..4a46ce4b 100644 --- a/src/modules/avformat/filter_avdeinterlace.c +++ b/src/modules/avformat/filter_avdeinterlace.c @@ -307,7 +307,8 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * writable = !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ); // Get the input image - error = mlt_frame_get_image( this, image, format, width, height, writable ); + *format = mlt_image_yuv422; + error = mlt_frame_get_image( this, image, format, width, height, 1 ); // Check that we want progressive and we aren't already progressive if ( deinterlace && *format == mlt_image_yuv422 && *image != NULL && !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ) ) @@ -316,11 +317,8 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * AVPicture *output = mlt_pool_alloc( sizeof( AVPicture ) ); // Fill the picture - if ( *format == mlt_image_yuv422 ) - { - avpicture_fill( output, *image, PIX_FMT_YUYV422, *width, *height ); - mlt_avpicture_deinterlace( output, output, PIX_FMT_YUYV422, *width, *height ); - } + avpicture_fill( output, *image, PIX_FMT_YUYV422, *width, *height ); + mlt_avpicture_deinterlace( output, output, PIX_FMT_YUYV422, *width, *height ); // Free the picture mlt_pool_release( output ); diff --git a/src/modules/avformat/filter_swscale.c b/src/modules/avformat/filter_swscale.c index d1266aea..a3ef5253 100644 --- a/src/modules/avformat/filter_swscale.c +++ b/src/modules/avformat/filter_swscale.c @@ -38,14 +38,6 @@ #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,6 +48,7 @@ static inline int convert_mlt_to_av_cs( mlt_image_format format ) value = PIX_FMT_RGB24; break; case mlt_image_rgb24a: + case mlt_image_opengl: value = PIX_FMT_RGB32; break; case mlt_image_yuv422: @@ -64,7 +57,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 +65,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 ); @@ -102,35 +94,37 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iform else if ( strcmp( interps, "spline" ) == 0 ) interp = SWS_SPLINE; - 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; + break; + case mlt_image_rgb24: + bpp = 3; + break; + case mlt_image_rgb24a: + case mlt_image_opengl: + bpp = 4; + break; + default: + // XXX: we only know how to rescale packed formats + return 1; + } // Convert the pixel formats - iformat = convert_mlt_to_av_cs( iformat ); - oformat = convert_mlt_to_av_cs( oformat ); - - avpicture_fill( &input, *image, iformat, iwidth, iheight ); - avpicture_fill( &output, outbuf, oformat, owidth, oheight ); + int avformat = convert_mlt_to_av_cs( *format ); - // Extract the alpha channel - if ( iformat == PIX_FMT_RGB32 && oformat == PIX_FMT_YUYV422 ) - { - // 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 ); - } - } + // 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 ); // Create the context and output image - struct SwsContext *context = sws_getContext( iwidth, iheight, iformat, owidth, oheight, oformat, interp, NULL, NULL, NULL); + struct SwsContext *context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL); assert(context); // Perform the scaling @@ -138,7 +132,7 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iform 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_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 ); @@ -154,11 +148,11 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iform uint8_t *alpha = mlt_frame_get_alpha_mask( this ); if ( alpha ) { - 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 ); + 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, oformat, 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); diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index caaaaebf..5b2919dc 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -41,6 +41,7 @@ #include #if LIBAVUTIL_VERSION_INT < (50<<16) +#define PIX_FMT_RGB32 PIX_FMT_RGBA32 #define PIX_FMT_YUYV422 PIX_FMT_YUV422 #endif @@ -611,6 +612,16 @@ static inline void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt, output.data, output.linesize); sws_freeContext( context ); } + else if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) + { + struct SwsContext *context = sws_getContext( width, height, pix_fmt, + width, height, PIX_FMT_RGBA, SWS_FAST_BILINEAR, NULL, NULL, NULL); + AVPicture output; + avpicture_fill( &output, buffer, PIX_FMT_RGBA, width, height ); + sws_scale( context, frame->data, frame->linesize, 0, height, + output.data, output.linesize); + sws_freeContext( context ); + } else { struct SwsContext *context = sws_getContext( width, height, pix_fmt, @@ -639,6 +650,12 @@ static inline void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt, avpicture_fill( &output, buffer, PIX_FMT_RGB24, width, height ); img_convert( &output, PIX_FMT_RGB24, (AVPicture *)frame, pix_fmt, width, height ); } + else if ( format == mlt_image_rgb24a || format == mlt_image_opengl ) + { + AVPicture output; + avpicture_fill( &output, buffer, PIX_FMT_RGB32, width, height ); + img_convert( &output, PIX_FMT_RGB32, (AVPicture *)frame, pix_fmt, width, height ); + } else { AVPicture output; @@ -673,6 +690,10 @@ static int allocate_buffer( mlt_properties frame_properties, AVCodecContext *cod case mlt_image_rgb24: size = *width * ( *height + 1 ) * 3; break; + case mlt_image_rgb24a: + case mlt_image_opengl: + size = *width * ( *height + 1 ) * 4; + break; default: *format = mlt_image_yuv422; size = *width * ( *height + 1 ) * 2; @@ -881,7 +902,8 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form if ( allocate_buffer( frame_properties, codec_context, buffer, format, width, height ) ) { convert_image( av_frame, *buffer, codec_context->pix_fmt, format, *width, *height ); - mlt_properties_set_int( frame_properties, "progressive", !av_frame->interlaced_frame ); + if ( !mlt_properties_get( properties, "force_progressive" ) ) + mlt_properties_set_int( frame_properties, "progressive", !av_frame->interlaced_frame ); mlt_properties_set_int( properties, "top_field_first", av_frame->top_field_first ); mlt_properties_set_int( properties, "_current_position", int_position ); mlt_properties_set_int( properties, "_got_picture", 1 ); @@ -1062,6 +1084,8 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) mlt_properties_set_int( frame_properties, "real_width", codec_context->width ); mlt_properties_set_int( frame_properties, "real_height", codec_context->height ); mlt_properties_set_double( frame_properties, "aspect_ratio", aspect_ratio ); + if ( mlt_properties_get( properties, "force_progressive" ) ) + mlt_properties_set_int( frame_properties, "progressive", mlt_properties_get_int( properties, "force_progressive" ) ); mlt_frame_push_get_image( frame, producer_get_image ); mlt_properties_set_data( frame_properties, "avformat_producer", this, 0, NULL, NULL ); diff --git a/src/modules/core/Makefile b/src/modules/core/Makefile index 3572821a..3d7c7024 100644 --- a/src/modules/core/Makefile +++ b/src/modules/core/Makefile @@ -16,6 +16,7 @@ OBJS = factory.o \ filter_data_show.o \ filter_gamma.o \ filter_greyscale.o \ + filter_imageconvert.o \ filter_luma.o \ filter_mirror.o \ filter_mono.o \ diff --git a/src/modules/core/factory.c b/src/modules/core/factory.c index 5d84e132..e6ae8896 100644 --- a/src/modules/core/factory.c +++ b/src/modules/core/factory.c @@ -29,6 +29,7 @@ extern mlt_filter filter_data_feed_init( mlt_profile profile, mlt_service_type t extern mlt_filter filter_data_show_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_gamma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_greyscale_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); +extern mlt_filter filter_imageconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_luma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_mirror_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_mono_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); @@ -60,6 +61,7 @@ MLT_REPOSITORY MLT_REGISTER( filter_type, "gamma", filter_gamma_init ); MLT_REGISTER( filter_type, "greyscale", filter_greyscale_init ); MLT_REGISTER( filter_type, "grayscale", filter_greyscale_init ); + MLT_REGISTER( filter_type, "imageconvert", filter_imageconvert_init ); MLT_REGISTER( filter_type, "luma", filter_luma_init ); MLT_REGISTER( filter_type, "mirror", filter_mirror_init ); MLT_REGISTER( filter_type, "mono", filter_mono_init ); diff --git a/src/modules/core/filter_brightness.c b/src/modules/core/filter_brightness.c index 07dce1c8..891f4b39 100644 --- a/src/modules/core/filter_brightness.c +++ b/src/modules/core/filter_brightness.c @@ -33,10 +33,11 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the image + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); // Only process if we have no error and a valid colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { // Get the brightness level double level = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "brightness" ); diff --git a/src/modules/core/filter_crop.c b/src/modules/core/filter_crop.c index 9068144a..ca1668f7 100644 --- a/src/modules/core/filter_crop.c +++ b/src/modules/core/filter_crop.c @@ -58,19 +58,23 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * *height = mlt_properties_get_int( properties, "normalised_height" ); } - // Now get the image - error = mlt_frame_get_image( this, image, format, width, height, writable ); - int left = mlt_properties_get_int( properties, "crop.left" ); int right = mlt_properties_get_int( properties, "crop.right" ); int top = mlt_properties_get_int( properties, "crop.top" ); int bottom = mlt_properties_get_int( properties, "crop.bottom" ); + + // We only know how to process yuv422 at the moment + if ( left || right || top || bottom ) + *format = mlt_image_yuv422; + + // Now get the image + error = mlt_frame_get_image( this, image, format, width, height, writable ); + int owidth = *width - left - right; int oheight = *height - top - bottom; - // We only know how to process yuv422 at the moment if ( ( owidth != *width || oheight != *height ) && - error == 0 && *format == mlt_image_yuv422 && *image != NULL && owidth > 0 && oheight > 0 ) + error == 0 && *image != NULL && owidth > 0 && oheight > 0 ) { // Provides a manual override for misreported field order if ( mlt_properties_get( properties, "meta.top_field_first" ) ) diff --git a/src/modules/core/filter_gamma.c b/src/modules/core/filter_gamma.c index e4fe15b3..08cfdcaa 100644 --- a/src/modules/core/filter_gamma.c +++ b/src/modules/core/filter_gamma.c @@ -30,9 +30,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { // Get the gamma value double gamma = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "gamma" ); diff --git a/src/modules/core/filter_greyscale.c b/src/modules/core/filter_greyscale.c index fd618c09..4d25abcc 100644 --- a/src/modules/core/filter_greyscale.c +++ b/src/modules/core/filter_greyscale.c @@ -29,8 +29,9 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { uint8_t *p = *image; uint8_t *q = *image + *width * *height * 2; diff --git a/src/modules/core/filter_imageconvert.c b/src/modules/core/filter_imageconvert.c new file mode 100644 index 00000000..dc07db72 --- /dev/null +++ b/src/modules/core/filter_imageconvert.c @@ -0,0 +1,469 @@ +/* + * filter_imageconvert.c -- colorspace and pixel format converter + * Copyright (C) 2009 Ushodaya Enterprises Limited + * Author: Dan Dennedy + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + + +static int convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total ) +{ + int ret = 0; + int yy, uu, vv; + int r,g,b; + total /= 2; + while (total--) + { + yy = yuv[0]; + uu = yuv[1]; + vv = yuv[3]; + YUV2RGB(yy, uu, vv, r, g, b); + rgba[0] = r; + rgba[1] = g; + rgba[2] = b; + rgba[3] = 255; + yy = yuv[2]; + YUV2RGB(yy, uu, vv, r, g, b); + rgba[4] = r; + rgba[5] = g; + rgba[6] = b; + rgba[7] = 255; + yuv += 4; + rgba += 8; + } + return ret; +} + +static int convert_yuv422_to_rgb24( uint8_t *yuv, uint8_t *rgb, unsigned int total ) +{ + int ret = 0; + int yy, uu, vv; + int r,g,b; + total /= 2; + while (total--) + { + yy = yuv[0]; + uu = yuv[1]; + vv = yuv[3]; + YUV2RGB(yy, uu, vv, r, g, b); + rgb[0] = r; + rgb[1] = g; + rgb[2] = b; + yy = yuv[2]; + YUV2RGB(yy, uu, vv, r, g, b); + rgb[3] = r; + rgb[4] = g; + rgb[5] = b; + yuv += 4; + rgb += 6; + } + return ret; +} + +static int convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha ) +{ + int ret = 0; + register int y0, y1, u0, u1, v0, v1; + register int r, g, b; + register uint8_t *d = yuv; + register int i, j; + + if ( alpha ) + for ( i = 0; i < height; i++ ) + { + register uint8_t *s = rgba + ( stride * i ); + for ( j = 0; j < ( width / 2 ); j++ ) + { + r = *s++; + g = *s++; + b = *s++; + *alpha++ = *s++; + RGB2YUV (r, g, b, y0, u0 , v0); + r = *s++; + g = *s++; + b = *s++; + *alpha++ = *s++; + RGB2YUV (r, g, b, y1, u1 , v1); + *d++ = y0; + *d++ = (u0+u1) >> 1; + *d++ = y1; + *d++ = (v0+v1) >> 1; + } + if ( width % 2 ) + { + r = *s++; + g = *s++; + b = *s++; + *alpha++ = *s++; + RGB2YUV (r, g, b, y0, u0 , v0); + *d++ = y0; + *d++ = u0; + } + } + else + for ( i = 0; i < height; i++ ) + { + register uint8_t *s = rgba + ( stride * i ); + for ( j = 0; j < ( width / 2 ); j++ ) + { + r = *s++; + g = *s++; + b = *s++; + s++; + RGB2YUV (r, g, b, y0, u0 , v0); + r = *s++; + g = *s++; + b = *s++; + s++; + RGB2YUV (r, g, b, y1, u1 , v1); + *d++ = y0; + *d++ = (u0+u1) >> 1; + *d++ = y1; + *d++ = (v0+v1) >> 1; + } + if ( width % 2 ) + { + r = *s++; + g = *s++; + b = *s++; + s++; + RGB2YUV (r, g, b, y0, u0 , v0); + *d++ = y0; + *d++ = u0; + } + } + + return ret; +} + +static int convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv ) +{ + int ret = 0; + register int y0, y1, u0, u1, v0, v1; + register int r, g, b; + register uint8_t *d = yuv; + register int i, j; + + for ( i = 0; i < height; i++ ) + { + register uint8_t *s = rgb + ( stride * i ); + for ( j = 0; j < ( width / 2 ); j++ ) + { + r = *s++; + g = *s++; + b = *s++; + RGB2YUV (r, g, b, y0, u0 , v0); + r = *s++; + g = *s++; + b = *s++; + RGB2YUV (r, g, b, y1, u1 , v1); + *d++ = y0; + *d++ = (u0+u1) >> 1; + *d++ = y1; + *d++ = (v0+v1) >> 1; + } + if ( width % 2 ) + { + r = *s++; + g = *s++; + b = *s++; + RGB2YUV (r, g, b, y0, u0 , v0); + *d++ = y0; + *d++ = u0; + } + } + return ret; +} + +static int convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, uint8_t *yuv ) +{ + int ret = 0; + register int i, j; + + int half = width >> 1; + + uint8_t *Y = yuv420p; + uint8_t *U = Y + width * height; + uint8_t *V = U + width * height / 4; + + register uint8_t *d = yuv; + + for ( i = 0; i < height; i++ ) + { + register uint8_t *u = U + ( i / 2 ) * ( half ); + register uint8_t *v = V + ( i / 2 ) * ( half ); + + for ( j = 0; j < half; j++ ) + { + *d ++ = *Y ++; + *d ++ = *u ++; + *d ++ = *Y ++; + *d ++ = *v ++; + } + } + return ret; +} + +static int convert_rgb24_to_rgb24a( uint8_t *rgb, uint8_t *rgba, int total ) +{ + uint8_t *s = rgb; + uint8_t *d = rgba; + while ( total-- ) + { + *d++ = s[0]; + *d++ = s[1]; + *d++ = s[2]; + *d++ = 0xff; + s += 3; + } + return 0; +} + +static int convert_rgb24a_to_rgb24( uint8_t *rgba, uint8_t *rgb, int total, uint8_t *alpha ) +{ + uint8_t *s = rgba; + uint8_t *d = rgb; + while ( total-- ) + { + *d++ = s[0]; + *d++ = s[1]; + *d++ = s[2]; + *alpha++ = s[3]; + s += 4; + } + return 0; +} + +static int convert_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, mlt_image_format requested_format ) +{ + int error = 0; + mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); + int width = mlt_properties_get_int( properties, "width" ); + int height = mlt_properties_get_int( properties, "height" ); + + if ( *format != requested_format ) + { + mlt_log_debug( NULL, "[filter imageconvert] %s -> %s\n", + mlt_image_format_name( *format ), mlt_image_format_name( requested_format ) ); + switch ( *format ) + { + case mlt_image_yuv422: + switch ( requested_format ) + { + case mlt_image_rgb24: + { + uint8_t *rgb = mlt_pool_alloc( width * height * 3 ); + error = convert_yuv422_to_rgb24( *buffer, rgb, width * height ); + if ( error ) + { + mlt_pool_release( rgb ); + } + else + { + mlt_properties_set_data( properties, "image", rgb, width * height * 3, mlt_pool_release, NULL ); + *buffer = rgb; + *format = mlt_image_rgb24; + } + break; + } + case mlt_image_rgb24a: + case mlt_image_opengl: + { + uint8_t *rgba = mlt_pool_alloc( width * height * 4 ); + error = convert_yuv422_to_rgb24a( *buffer, rgba, width * height ); + if ( error ) + { + mlt_pool_release( rgba ); + } + else + { + mlt_properties_set_data( properties, "image", rgba, width * height * 4, mlt_pool_release, NULL ); + *buffer = rgba; + *format = requested_format; + } + break; + } + default: + error = 1; + } + break; + case mlt_image_rgb24: + switch ( requested_format ) + { + case mlt_image_yuv422: + { + uint8_t *yuv = mlt_pool_alloc( width * height * 2 ); + error = convert_rgb24_to_yuv422( *buffer, width, height, width * 3, yuv ); + if ( error ) + { + mlt_pool_release( yuv ); + } + else + { + mlt_properties_set_data( properties, "image", yuv, width * height * 2, mlt_pool_release, NULL ); + *buffer = yuv; + *format = mlt_image_yuv422; + } + break; + } + case mlt_image_rgb24a: + case mlt_image_opengl: + { + uint8_t *rgba = mlt_pool_alloc( width * height * 4 ); + error = convert_rgb24_to_rgb24a( *buffer, rgba, width * height ); + if ( error ) + { + mlt_pool_release( rgba ); + } + else + { + mlt_properties_set_data( properties, "image", rgba, width * height * 4, mlt_pool_release, NULL ); + *buffer = rgba; + *format = requested_format; + } + break; + } + default: + error = 1; + } + break; + case mlt_image_rgb24a: + case mlt_image_opengl: + switch ( requested_format ) + { + case mlt_image_yuv422: + { + uint8_t *yuv = mlt_pool_alloc( width * height * 2 ); + uint8_t *alpha = mlt_pool_alloc( width * height ); + error = convert_rgb24a_to_yuv422( *buffer, width, height, width * 4, yuv, alpha ); + if ( error ) + { + mlt_pool_release( yuv ); + mlt_pool_release( alpha ); + } + else + { + mlt_properties_set_data( properties, "image", yuv, width * height * 2, mlt_pool_release, NULL ); + mlt_properties_set_data( properties, "alpha", alpha, width * height, mlt_pool_release, NULL ); + *buffer = yuv; + *format = mlt_image_yuv422; + } + break; + } + case mlt_image_rgb24: + { + uint8_t *rgb = mlt_pool_alloc( width * height * 3 ); + uint8_t *alpha = mlt_pool_alloc( width * height ); + error = convert_rgb24a_to_rgb24( *buffer, rgb, width * height, alpha ); + if ( error ) + { + mlt_pool_release( rgb ); + mlt_pool_release( alpha ); + } + else + { + mlt_properties_set_data( properties, "image", rgb, width * height * 3, mlt_pool_release, NULL ); + mlt_properties_set_data( properties, "alpha", alpha, width * height, mlt_pool_release, NULL ); + *buffer = rgb; + *format = mlt_image_rgb24; + } + break; + } + case mlt_image_rgb24a: + case mlt_image_opengl: + *format = requested_format; + break; + default: + error = 1; + } + break; + case mlt_image_yuv420p: + switch ( requested_format ) + { + case mlt_image_rgb24: + case mlt_image_rgb24a: + case mlt_image_opengl: + case mlt_image_yuv422: + { + uint8_t *yuv = mlt_pool_alloc( width * height * 2 ); + int error = convert_yuv420p_to_yuv422( *buffer, width, height, yuv ); + if ( error ) + { + mlt_pool_release( yuv ); + } + else + { + mlt_properties_set_data( properties, "image", yuv, width * height * 2, mlt_pool_release, NULL ); + *buffer = yuv; + *format = mlt_image_yuv422; + } + switch ( requested_format ) + { + case mlt_image_yuv422: + break; + case mlt_image_rgb24: + case mlt_image_rgb24a: + case mlt_image_opengl: + error = convert_image( frame, buffer, format, requested_format ); + break; + default: + error = 1; + break; + } + break; + } + default: + error = 1; + } + break; + default: + error = 1; + } + } + if ( !error ) + mlt_properties_set_int( properties, "format", *format ); + + return error; +} + +/** Filter processing. +*/ + +static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) +{ + frame->convert_image = convert_image; + return frame; +} + +/** Constructor for the filter. +*/ + +mlt_filter filter_imageconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) +{ + mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 ); + if ( mlt_filter_init( this, this ) == 0 ) + { + this->process = filter_process; + } + return this; +} diff --git a/src/modules/core/filter_luma.c b/src/modules/core/filter_luma.c index f05d6c40..04f52a2a 100644 --- a/src/modules/core/filter_luma.c +++ b/src/modules/core/filter_luma.c @@ -43,6 +43,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * if ( out == 0 ) out = 24; + *format = mlt_image_yuv422; if ( b_frame == NULL || mlt_properties_get_int( b_frame_props, "width" ) != *width || mlt_properties_get_int( b_frame_props, "height" ) != *height ) { diff --git a/src/modules/core/filter_mirror.c b/src/modules/core/filter_mirror.c index 3dd6dbfc..813aeef8 100644 --- a/src/modules/core/filter_mirror.c +++ b/src/modules/core/filter_mirror.c @@ -43,13 +43,14 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format int reverse = mlt_properties_get_int( properties, "reverse" ); // Get the image + *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Get the alpha uint8_t *alpha = mlt_frame_get_alpha_mask( frame ); // If we have an image of the right colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { // We'll KISS here int hh = *height / 2; diff --git a/src/modules/core/filter_obscure.c b/src/modules/core/filter_obscure.c index 7256f6cc..8ccebba5 100644 --- a/src/modules/core/filter_obscure.c +++ b/src/modules/core/filter_obscure.c @@ -236,10 +236,11 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format mlt_filter this = mlt_frame_pop_service( frame ); // Get the image from the frame + *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Get the image from the frame - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { if ( this != NULL ) { diff --git a/src/modules/core/filter_rescale.c b/src/modules/core/filter_rescale.c index f4594d8b..540e0ca6 100644 --- a/src/modules/core/filter_rescale.c +++ b/src/modules/core/filter_rescale.c @@ -20,97 +20,101 @@ #include #include +#include #include #include #include #include -typedef int ( *image_scaler )( mlt_frame this, uint8_t **image, mlt_image_format iformat, mlt_image_format oformat, int iwidth, int iheight, int owidth, int oheight ); +/** virtual function declaration for an image scaler + * + * image scaler implementations are expected to support the following in and out formats: + * yuv422 -> yuv422 + * rgb24 -> rgb24 + * rgb24a -> rgb24a + * rgb24 -> yuv422 + * rgb24a -> yuv422 + */ -static void scale_alpha( mlt_frame this, int iwidth, int iheight, int owidth, int oheight ); +typedef int ( *image_scaler )( mlt_frame this, uint8_t **image, mlt_image_format *format, int iwidth, int iheight, int owidth, int oheight ); -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 ); - // Get the rescaling interpolsation - char *interps = mlt_properties_get( properties, "rescale.interp" ); + // Convert the image to yuv422 + *format = mlt_image_yuv422; + mlt_frame_get_image( this, image, format, &iwidth, &iheight, 0 ); - // Carry out the rescaling - if ( iformat == mlt_image_yuv422 && oformat == mlt_image_yuv422 ) - { - // Scale the frame - mlt_frame_rescale_yuv422( this, owidth, oheight ); - - // Return the output - *image = mlt_properties_get_data( properties, "image", NULL ); - } - else if ( iformat == mlt_image_rgb24 || iformat == mlt_image_rgb24a ) - { - int bpp = (iformat == mlt_image_rgb24a ? 4 : 3 ); - - // Create the yuv image - uint8_t *output = mlt_pool_alloc( iwidth * ( iheight + 1 ) * 2 ); + // Create the output image + uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 ); - if ( strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) ) - { - // Extract YUV422 and alpha - if ( bpp == 4 ) - { - // Allocate the alpha mask - uint8_t *alpha = mlt_pool_alloc( iwidth * ( iheight + 1 ) ); + // Calculate strides + int istride = iwidth * 2; + int ostride = owidth * 2; + iwidth = iwidth - ( iwidth % 4 ); - // Convert the image and extract alpha - mlt_convert_rgb24a_to_yuv422( *image, iwidth, iheight, iwidth * 4, output, alpha ); + // Derived coordinates + int dy, dx; - mlt_properties_set_data( properties, "alpha", alpha, iwidth * ( iheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL ); + // Calculate ranges + int out_x_range = owidth / 2; + int out_y_range = oheight / 2; + int in_x_range = iwidth / 2; + int in_y_range = iheight / 2; - scale_alpha( this, iwidth, iheight, owidth, oheight ); - } - else - { - // No alpha to extract - mlt_convert_rgb24_to_yuv422( *image, iwidth, iheight, iwidth * 3, output ); - } + // Output pointers + register uint8_t *out_line = output; + register uint8_t *out_ptr; - mlt_properties_set_data( properties, "image", output, iwidth * ( iheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL ); + // Calculate a middle pointer + uint8_t *in_middle = *image + istride * in_y_range + in_x_range * 2; + uint8_t *in_line; - // Scale the frame - output = mlt_frame_rescale_yuv422( this, owidth, oheight ); + // Generate the affine transform scaling values + register int scale_width = ( iwidth << 16 ) / owidth; + register int scale_height = ( iheight << 16 ) / oheight; + register int base = 0; - } - else - { - // Extract YUV422 and alpha - if ( bpp == 4 ) - { - // Allocate the alpha mask - uint8_t *alpha = mlt_pool_alloc( owidth * ( oheight + 1 ) ); + int outer = out_x_range * scale_width; + int bottom = out_y_range * scale_height; - // Convert the image and extract alpha - mlt_convert_rgb24a_to_yuv422( *image, owidth, oheight, owidth * 4, output, alpha ); + // Loop for the entirety of our output height. + for ( dy = - bottom; dy < bottom; dy += scale_height ) + { + // Start at the beginning of the line + out_ptr = out_line; - mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL ); + // Pointer to the middle of the input line + in_line = in_middle + ( dy >> 16 ) * istride; - scale_alpha( this, iwidth, iheight, owidth, oheight ); - } - else - { - // No alpha to extract - mlt_convert_rgb24_to_yuv422( *image, owidth, oheight, owidth * 3, output ); - } + // Loop for the entirety of our output row. + for ( dx = - outer; dx < outer; dx += scale_width ) + { + base = dx >> 15; + base &= 0xfffffffe; + *out_ptr ++ = *( in_line + base ); + base &= 0xfffffffc; + *out_ptr ++ = *( in_line + base + 1 ); + dx += scale_width; + base = dx >> 15; + base &= 0xfffffffe; + *out_ptr ++ = *( in_line + base ); + base &= 0xfffffffc; + *out_ptr ++ = *( in_line + base + 3 ); } - - // Now update the frame - 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 ); - - *image = output; + // Move to next output line + out_line += ostride; } + + // Now update the frame + 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 ); + *image = output; return 0; } @@ -172,7 +176,6 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * int owidth = *width; int oheight = *height; char *interps = mlt_properties_get( properties, "rescale.interp" ); - int wanted_format = *format; // Default from the scaler if not specifed on the frame if ( interps == NULL ) @@ -189,7 +192,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * } // Let the producer know what we are actually requested to obtain - if ( *format == mlt_image_yuv422 && strcmp( interps, "none" ) ) + if ( strcmp( interps, "none" ) ) { mlt_properties_set_int( properties, "rescale_width", *width ); mlt_properties_set_int( properties, "rescale_height", *height ); @@ -212,53 +215,25 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * // Get rescale interpretation again, in case the producer wishes to override scaling interps = mlt_properties_get( properties, "rescale.interp" ); - if ( *image != NULL && ( *format != mlt_image_yuv422 || ( iwidth != owidth || iheight != oheight ) ) ) + if ( *image && strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) ) { - // If the colour space is correct and scaling is off, do nothing - if ( *format == mlt_image_yuv422 && !strcmp( interps, "none" ) ) - { - *width = iwidth; - *height = iheight; - } - else if ( *format == mlt_image_yuv422 ) - { - // Call the local scaler - scaler_method( this, image, *format, mlt_image_yuv422, iwidth, iheight, owidth, oheight ); - *width = owidth; - *height = oheight; - } - else if ( *format == mlt_image_rgb24 && wanted_format == mlt_image_rgb24 ) - { - // Call the local scaler - scaler_method( this, image, *format, mlt_image_rgb24, iwidth, iheight, owidth, oheight ); + mlt_log_debug( MLT_FILTER_SERVICE( filter ), "%dx%d -> %dx%d (%s)\n", + iwidth, iheight, owidth, oheight, mlt_image_format_name( *format ) ); - // Return the output - *width = owidth; - *height = oheight; - } - else if ( *format == mlt_image_rgb24 || *format == mlt_image_rgb24a ) + // If valid colorspace + if ( *format == mlt_image_yuv422 || *format == mlt_image_rgb24 || + *format == mlt_image_rgb24a || *format == mlt_image_opengl ) { - // Call the local scaler - scaler_method( this, image, *format, mlt_image_yuv422, iwidth, iheight, owidth, oheight ); - - // Return the output - *format = mlt_image_yuv422; + // Call the virtual function + scaler_method( this, image, format, iwidth, iheight, owidth, oheight ); *width = owidth; *height = oheight; } - else - { - *width = iwidth; - *height = iheight; - } - if ( *width == owidth ) - { - // 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 ) && alpha_size != ( owidth * ( oheight + 1 ) ) ) - scale_alpha( this, iwidth, iheight, 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 ) && alpha_size != ( owidth * ( oheight + 1 ) ) ) + scale_alpha( this, iwidth, iheight, owidth, oheight ); } else { diff --git a/src/modules/core/filter_resize.c b/src/modules/core/filter_resize.c index 68244bfc..e57c90ff 100644 --- a/src/modules/core/filter_resize.c +++ b/src/modules/core/filter_resize.c @@ -36,6 +36,145 @@ static inline void swap_bytes( uint8_t *upper, uint8_t *lower ) *upper = t; } +static uint8_t *resize_alpha( uint8_t *input, int owidth, int oheight, int iwidth, int iheight, uint8_t alpha_value ) +{ + uint8_t *output = NULL; + + if ( input != NULL && ( iwidth != owidth || iheight != oheight ) && ( owidth > 6 && oheight > 6 ) ) + { + uint8_t *out_line; + int offset_x = ( owidth - iwidth ) / 2; + int offset_y = ( oheight - iheight ) / 2; + int iused = iwidth; + + output = mlt_pool_alloc( owidth * oheight ); + memset( output, alpha_value, owidth * oheight ); + + offset_x -= offset_x % 2; + + out_line = output + offset_y * owidth; + out_line += offset_x; + + // Loop for the entirety of our output height. + while ( iheight -- ) + { + // We're in the input range for this row. + memcpy( out_line, input, iused ); + + // Move to next input line + input += iwidth; + + // Move to next output line + out_line += owidth; + } + } + + return output; +} + +static void resize_image( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight, int bpp ) +{ + // Calculate strides + int istride = iwidth * bpp; + int ostride = owidth * bpp; + int offset_x = ( owidth - iwidth ) / 2 * bpp; + int offset_y = ( oheight - iheight ) / 2; + uint8_t *in_line = input; + uint8_t *out_line; + int size = owidth * oheight; + uint8_t *p = output; + + // Optimisation point + if ( output == NULL || input == NULL || ( owidth <= 6 || oheight <= 6 || iwidth <= 6 || oheight <= 6 ) ) + { + return; + } + else if ( iwidth == owidth && iheight == oheight ) + { + memcpy( output, input, iheight * istride ); + return; + } + + if ( bpp == 2 ) + { + while( size -- ) + { + *p ++ = 16; + *p ++ = 128; + } + offset_x -= offset_x % 4; + } + else + { + size *= bpp; + while ( size-- ) + *p ++ = 0; + } + + out_line = output + offset_y * ostride; + out_line += offset_x; + + // Loop for the entirety of our output height. + while ( iheight -- ) + { + // We're in the input range for this row. + memcpy( out_line, in_line, iwidth * bpp ); + + // Move to next input line + in_line += istride; + + // Move to next output line + out_line += ostride; + } +} + +/** A resizing function for yuv422 frames - this does not rescale, but simply + resizes. It assumes yuv422 images available on the frame so use with care. +*/ + +static uint8_t *frame_resize_image( mlt_frame this, int owidth, int oheight, int bpp ) +{ + // Get properties + mlt_properties properties = MLT_FRAME_PROPERTIES( this ); + + // Get the input image, width and height + uint8_t *input = mlt_properties_get_data( properties, "image", NULL ); + uint8_t *alpha = mlt_frame_get_alpha_mask( this ); + + int iwidth = mlt_properties_get_int( properties, "width" ); + int iheight = mlt_properties_get_int( properties, "height" ); + + // If width and height are correct, don't do anything + if ( iwidth != owidth || iheight != oheight ) + { + uint8_t alpha_value = mlt_properties_get_int( properties, "resize_alpha" ); + + // Create the output image + uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * bpp ); + + // Call the generic resize + resize_image( output, owidth, oheight, input, iwidth, iheight, bpp ); + + // Now update the frame + mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * bpp, ( mlt_destructor )mlt_pool_release, NULL ); + mlt_properties_set_int( properties, "width", owidth ); + mlt_properties_set_int( properties, "height", oheight ); + + // We should resize the alpha too + alpha = resize_alpha( alpha, owidth, oheight, iwidth, iheight, alpha_value ); + if ( alpha != NULL ) + { + mlt_properties_set_data( properties, "alpha", alpha, owidth * oheight, ( mlt_destructor )mlt_pool_release, NULL ); + this->get_alpha_mask = NULL; + } + + // Return the output + return output; + } + // No change, return input + return input; +} + /** Do it :-). */ @@ -120,11 +259,28 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * // Now get the image error = mlt_frame_get_image( this, image, format, &owidth, &oheight, writable ); - // We only know how to process yuv422 at the moment - if ( error == 0 && *format == mlt_image_yuv422 && *image != NULL ) + if ( error == 0 && *image ) { // Get the requested scale operation char *op = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "scale" ); + int bpp; + + switch ( *format ) + { + case mlt_image_yuv422: + bpp = 2; + break; + case mlt_image_rgb24: + bpp = 3; + break; + case mlt_image_rgb24a: + case mlt_image_opengl: + bpp = 4; + break; + default: + // XXX: we only know how to resize packed formats + return 1; + } // Provides a manual override for misreported field order if ( mlt_properties_get( properties, "meta.top_field_first" ) ) @@ -136,8 +292,8 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * // Get the input image, width and height int size; uint8_t *image = mlt_properties_get_data( properties, "image", &size ); - uint8_t *ptr = image + owidth * 2; - memmove( ptr, image, size - owidth * 2 ); + uint8_t *ptr = image + owidth * bpp; + memmove( ptr, image, size - owidth * bpp ); // Set the normalised field order mlt_properties_set_int( properties, "top_field_first", 0 ); @@ -146,11 +302,12 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * if ( !strcmp( op, "affine" ) ) { - *image = mlt_frame_rescale_yuv422( this, *width, *height ); + // TODO: Determine where this is needed and find a different way + // *image = mlt_frame_rescale_image( this, *width, *height, bpp ); } else if ( strcmp( op, "none" ) != 0 ) { - *image = mlt_frame_resize_yuv422( this, *width, *height ); + *image = frame_resize_image( this, *width, *height, bpp ); } else { diff --git a/src/modules/core/filter_watermark.c b/src/modules/core/filter_watermark.c index f1ab0e41..e1e95d62 100644 --- a/src/modules/core/filter_watermark.c +++ b/src/modules/core/filter_watermark.c @@ -165,6 +165,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format mlt_properties_set_int( b_props, "distort", 1 ); } + *format = mlt_image_yuv422; if ( mlt_properties_get_int( properties, "reverse" ) == 0 ) { // Apply all filters that are attached to this filter to the b frame diff --git a/src/modules/core/loader.ini b/src/modules/core/loader.ini index bcb25608..cf7b62ec 100644 --- a/src/modules/core/loader.ini +++ b/src/modules/core/loader.ini @@ -6,9 +6,15 @@ # The names of the services on the right dictate the preference used (if unavailable # the second and third are applied as applicable). +# image filters crop=crop:1 deinterlace=deinterlace,avdeinterlace rescaler=mcrescale,gtkrescale,rescale,swscale resizer=resize +imageconverter=imageconvert,avcolour_space + +# audio filters resampler=resample,soxresample,avresample + +# metadata filters data=data_feed:attr_check diff --git a/src/modules/core/producer_colour.c b/src/modules/core/producer_colour.c index ac420017..ad2a5ae0 100644 --- a/src/modules/core/producer_colour.c +++ b/src/modules/core/producer_colour.c @@ -93,9 +93,6 @@ rgba_color parse_color( char *color, unsigned int color_int ) static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) { - // May need to know the size of the image to clone it - int size = 0; - // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); @@ -110,9 +107,11 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form char *then = mlt_properties_get( producer_props, "_resource" ); // Get the current image and dimensions cached in the producer + int size = 0; uint8_t *image = mlt_properties_get_data( producer_props, "image", &size ); int current_width = mlt_properties_get_int( producer_props, "_width" ); int current_height = mlt_properties_get_int( producer_props, "_height" ); + mlt_image_format current_format = mlt_properties_get_int( producer_props, "_format" ); // Parse the colour if ( now && strchr( now, '/' ) ) @@ -123,78 +122,105 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form rgba_color color = parse_color( now, mlt_properties_get_int( producer_props, "resource" ) ); // See if we need to regenerate - if ( strcmp( now, then ) || *width != current_width || *height != current_height ) + if ( strcmp( now, then ) || *width != current_width || *height != current_height || *format != current_format ) { // Color the image - uint8_t y, u, v; - int i = *height; - int j = 0; - int uneven = *width % 2; - int count = ( *width - uneven ) / 2; - uint8_t *p = NULL; + int i = *width * *height + 1; + int bpp; + + switch ( *format ) + { + case mlt_image_rgb24: + bpp = 3; + break; + case mlt_image_rgb24a: + case mlt_image_opengl: + bpp = 4; + break; + default: + bpp = 2; + *format = mlt_image_yuv422; + break; + } // Allocate the image - size = *width * *height * 2; - image = mlt_pool_alloc( size ); + size = *width * *height * bpp; + uint8_t *p = image = mlt_pool_alloc( size ); // Update the producer mlt_properties_set_data( producer_props, "image", image, size, mlt_pool_release, NULL ); mlt_properties_set_int( producer_props, "_width", *width ); mlt_properties_set_int( producer_props, "_height", *height ); + mlt_properties_set_int( producer_props, "_format", *format ); mlt_properties_set( producer_props, "_resource", now ); - RGB2YUV( color.r, color.g, color.b, y, u, v ); - - p = image; - - while ( i -- ) + switch ( *format ) { - j = count; - while ( j -- ) + case mlt_image_yuv422: + { + int uneven = *width % 2; + int count = ( *width - uneven ) / 2 + 1; + uint8_t y, u, v; + + RGB2YUV( color.r, color.g, color.b, y, u, v ); + i = *height + 1; + while ( --i ) { - *p ++ = y; - *p ++ = u; - *p ++ = y; - *p ++ = v; + int j = count; + while ( --j ) + { + *p ++ = y; + *p ++ = u; + *p ++ = y; + *p ++ = v; + } + if ( uneven ) + { + *p ++ = y; + *p ++ = u; + } } - if ( uneven ) + break; + } + case mlt_image_rgb24: + while ( --i ) + { + *p ++ = color.r; + *p ++ = color.g; + *p ++ = color.b; + } + break; + case mlt_image_rgb24a: + case mlt_image_opengl: + while ( --i ) { - *p ++ = y; - *p ++ = u; + *p ++ = color.r; + *p ++ = color.g; + *p ++ = color.b; + *p ++ = color.a; } + break; + default: + break; } } - // Update the frame - mlt_properties_set_int( properties, "width", *width ); - mlt_properties_set_int( properties, "height", *height ); - - // Clone if necessary (deemed always necessary) - if ( 1 ) - { - // Create the alpha channel - uint8_t *alpha = mlt_pool_alloc( size >> 1 ); + // Create the alpha channel + int alpha_size = *width * *height; + uint8_t *alpha = mlt_pool_alloc( alpha_size ); - // Clone our image - uint8_t *copy = mlt_pool_alloc( size ); - memcpy( copy, image, size ); + // Initialise the alpha + if ( alpha ) + memset( alpha, color.a, alpha_size ); - // We're going to pass the copy on - image = copy; - - // Initialise the alpha - if ( alpha ) - memset( alpha, color.a, size >> 1 ); - - // Now update properties so we free the copy after - mlt_properties_set_data( properties, "image", copy, size, mlt_pool_release, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, size >> 1, mlt_pool_release, NULL ); - mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) ); - } + // Clone our image + *buffer = mlt_pool_alloc( size ); + memcpy( *buffer, image, size ); - // Pass on the image - *buffer = image; - *format = mlt_image_yuv422; + // Now update properties so we free the copy after + mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL ); + mlt_properties_set_data( properties, "alpha", alpha, alpha_size, mlt_pool_release, NULL ); + mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) ); return 0; } diff --git a/src/modules/core/producer_consumer.c b/src/modules/core/producer_consumer.c index 9f4992cb..4baa186f 100644 --- a/src/modules/core/producer_consumer.c +++ b/src/modules/core/producer_consumer.c @@ -46,7 +46,8 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format int result = mlt_frame_get_image( nested_frame, image, format, width, height, writable ); // Allocate the image - int size = *width * *height * ( *format == mlt_image_yuv422 ? 2 : *format == mlt_image_rgb24 ? 3 : *format == mlt_image_rgb24a ? 4 : ( 3 / 2 ) ); + int size = *width * *height * ( *format == mlt_image_yuv422 ? 2 : *format == mlt_image_rgb24 ? 3 : + ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) ? 4 : ( 3 / 2 ) ); uint8_t *new_image = mlt_pool_alloc( size ); // Update the frame diff --git a/src/modules/core/producer_ppm.c b/src/modules/core/producer_ppm.c index 01215790..faa27926 100644 --- a/src/modules/core/producer_ppm.c +++ b/src/modules/core/producer_ppm.c @@ -73,24 +73,10 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma if ( mlt_properties_get_int( properties, "has_image" ) ) { // Get the RGB image - uint8_t *rgb = mlt_properties_get_data( properties, "image", NULL ); - - // Get width and height + *buffer = mlt_properties_get_data( properties, "image", NULL ); *width = mlt_properties_get_int( properties, "width" ); *height = mlt_properties_get_int( properties, "height" ); - - // Convert to requested format - if ( *format == mlt_image_yuv422 ) - { - uint8_t *image = mlt_pool_alloc( *width * ( *height + 1 ) * 2 ); - mlt_convert_rgb24_to_yuv422( rgb, *width, *height, *width * 3, image ); - mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL ); - *buffer = image; - } - else if ( *format == mlt_image_rgb24 ) - { - *buffer = rgb; - } + *format = mlt_image_rgb24; } else { @@ -113,7 +99,7 @@ FILE *producer_ppm_run_video( producer_ppm this ) char command[ 1024 ]; float fps = mlt_producer_get_fps( &this->parent ); float position = mlt_producer_position( &this->parent ); - sprintf( command, "ffmpeg -i \"%s\" -ss %f -f imagepipe -r %f -img ppm - 2>/dev/null", this->command, position, fps ); + sprintf( command, "ffmpeg -i \"%s\" -ss %f -f image2pipe -r %f -vcodec ppm - 2>/dev/null", this->command, position, fps ); this->video = popen( command, "r" ); } } diff --git a/src/modules/core/transition_luma.c b/src/modules/core/transition_luma.c index 3a4eb168..acd15f1b 100644 --- a/src/modules/core/transition_luma.c +++ b/src/modules/core/transition_luma.c @@ -137,9 +137,6 @@ static void luma_composite( mlt_frame a_frame, mlt_frame b_frame, int luma_width int stride_dest; uint16_t weight = 0; - format_src = mlt_image_yuv422; - format_dest = mlt_image_yuv422; - if ( mlt_properties_get( &a_frame->parent, "distort" ) ) mlt_properties_set( &b_frame->parent, "distort", mlt_properties_get( &a_frame->parent, "distort" ) ); mlt_properties_set_int( &b_frame->parent, "consumer_deinterlace", mlt_properties_get_int( &a_frame->parent, "consumer_deinterlace" ) ); @@ -348,12 +345,6 @@ static void luma_read_yuv422( uint8_t *image, uint16_t **map, int width, int hei *p++ = ( image[ i ] - 16 ) * 299; // 299 = 65535 / 219 } -/** Generate a luma map from a YUV image. -*/ -static void luma_read_rgb24( uint8_t *image, uint16_t **map, int width, int height ) -{ -} - /** Get the image. */ @@ -470,11 +461,8 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f mlt_frame_get_image( luma_frame, &luma_image, &luma_format, &luma_width, &luma_height, 0 ); // Generate the luma map - if ( luma_image != NULL && luma_format == mlt_image_yuv422 ) + if ( luma_image != NULL ) luma_read_yuv422( luma_image, &luma_bitmap, luma_width, luma_height ); - - else if ( luma_image != NULL && luma_format == mlt_image_rgb24 ) - luma_read_rgb24( luma_image, &luma_bitmap, luma_width, luma_height ); // Set the transition properties mlt_properties_set_int( properties, "width", luma_width ); diff --git a/src/modules/effectv/filter_burn.c b/src/modules/effectv/filter_burn.c index 967e2630..8747d2be 100644 --- a/src/modules/effectv/filter_burn.c +++ b/src/modules/effectv/filter_burn.c @@ -71,10 +71,11 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * mlt_filter filter = mlt_frame_pop_service( this ); // Get the image + *format = mlt_image_rgb24a; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); // Only process if we have no error and a valid colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { // Get the "Burn the foreground" value int burn_foreground = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "foreground" ); @@ -90,15 +91,12 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * int video_height = *height; int video_area = video_width * video_height; // We need to create a new frame as this effect modifies the input - RGB32 *dest = mlt_pool_alloc( video_area * sizeof(RGB32) ); - RGB32 *src = (RGB32*)dest; + RGB32 *dest = (RGB32*)*image; + RGB32 *src = (RGB32*)*image; unsigned char v, w; RGB32 a, b; - mlt_convert_yuv422_to_rgb24a(*image, (uint8_t *)dest, video_area); - - diff = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), "_diff", NULL ); if (diff == NULL) @@ -170,11 +168,6 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * } i += 2; } - - mlt_convert_rgb24a_to_yuv422((uint8_t *)dest, *width, *height, *width * sizeof(RGB32), - *image, NULL ); - - mlt_pool_release(dest); } return error; diff --git a/src/modules/frei0r/filter_frei0r.c b/src/modules/frei0r/filter_frei0r.c index a2880f15..eb699d32 100644 --- a/src/modules/frei0r/filter_frei0r.c +++ b/src/modules/frei0r/filter_frei0r.c @@ -25,16 +25,18 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * { mlt_filter filter = mlt_frame_pop_service( this ); - int error = mlt_frame_get_image( this, image, format, width, height, 1 ); + *format = mlt_image_rgb24a; + mlt_log_debug( MLT_FILTER_SERVICE( filter ), "frei0r %dx%d\n", *width, *height ); + int error = mlt_frame_get_image( this, image, format, width, height, 0 ); - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { mlt_position in = mlt_filter_get_in( filter ); mlt_position out = mlt_filter_get_out( filter ); mlt_position time = mlt_frame_get_position( this ); double position = ( double )( time - in ) / ( double )( out - in + 1 ); - process_frei0r_item( filter_type , position, MLT_FILTER_PROPERTIES ( filter ), this , image, format , width , height , writable ); + process_frei0r_item( filter_type, position, MLT_FILTER_PROPERTIES ( filter ), this, image, width, height ); } @@ -49,8 +51,7 @@ mlt_frame filter_process( mlt_filter this, mlt_frame frame ) return frame; } -void filter_close( mlt_filter this ){ - +void filter_close( mlt_filter this ) +{ destruct( MLT_FILTER_PROPERTIES ( this ) ); - } diff --git a/src/modules/frei0r/frei0r_helper.c b/src/modules/frei0r/frei0r_helper.c index e42b06e3..148d679d 100644 --- a/src/modules/frei0r/frei0r_helper.c +++ b/src/modules/frei0r/frei0r_helper.c @@ -31,8 +31,8 @@ static void parse_color( int color, f0r_param_color_t *fcolor ) fcolor->b /= 255; } -int process_frei0r_item( mlt_service_type type, double position , mlt_properties prop , mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){ - +int process_frei0r_item( mlt_service_type type, double position, mlt_properties prop, mlt_frame this, uint8_t **image, int *width, int *height ) +{ int i=0; f0r_instance_t ( *f0r_construct ) ( unsigned int , unsigned int ) = mlt_properties_get_data( prop , "f0r_construct" ,NULL); void (*f0r_update)(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)=mlt_properties_get_data( prop , "f0r_update" ,NULL); @@ -101,35 +101,17 @@ int process_frei0r_item( mlt_service_type type, double position , mlt_propertie } int video_area = *width * *height; - uint32_t *img_a; - - if ( type != producer_type ) - img_a = mlt_pool_alloc( video_area * sizeof(uint32_t) ); - uint32_t *img_b = mlt_pool_alloc( video_area * sizeof(uint32_t) ); + uint32_t *result = mlt_pool_alloc( video_area * sizeof(uint32_t) ); if (type==producer_type) { - f0r_update ( inst , position , NULL , img_b ); - mlt_convert_rgb24a_to_yuv422((uint8_t *)img_b , *width, *height, *width * sizeof(uint32_t),*image, NULL); + f0r_update (inst, position, NULL, result ); } else if (type==filter_type) { - mlt_convert_yuv422_to_rgb24a(*image, (uint8_t *)img_a, video_area); - f0r_update ( inst , position , img_a , img_b ); - mlt_convert_rgb24a_to_yuv422((uint8_t *)img_b , *width, *height, *width * sizeof(uint32_t), - *image, NULL ); + f0r_update ( inst, position, (uint32_t *)image[0], result ); } else if (type==transition_type && f0r_update2 ){ - uint32_t *result = mlt_pool_alloc( video_area * sizeof(uint32_t) ); - - mlt_convert_yuv422_to_rgb24a ( image[0] , (uint8_t *)img_a , video_area ); - mlt_convert_yuv422_to_rgb24a ( image[1] , (uint8_t *)img_b , video_area ); - f0r_update2 ( inst , position , img_a , img_b , NULL , result ); - - uint8_t * image_ptr=mlt_properties_get_data(MLT_FRAME_PROPERTIES(this), "image", NULL ); - if (image_ptr) - mlt_convert_rgb24a_to_yuv422((uint8_t *)result, *width, *height, *width * sizeof(uint32_t), image_ptr , NULL ); - - mlt_pool_release(result); - } - if ( type != producer_type ) mlt_pool_release(img_a); - mlt_pool_release(img_b); + f0r_update2 ( inst, position, (uint32_t *)image[0], (uint32_t *)image[1], NULL, result ); + } + *image = (uint8_t*) result; + mlt_properties_set_data(MLT_FRAME_PROPERTIES(this), "image", result, video_area * sizeof(uint32_t), mlt_pool_release, NULL); return 0; } diff --git a/src/modules/frei0r/frei0r_helper.h b/src/modules/frei0r/frei0r_helper.h index aee4a5d2..2b917664 100644 --- a/src/modules/frei0r/frei0r_helper.h +++ b/src/modules/frei0r/frei0r_helper.h @@ -18,5 +18,6 @@ */ #include -int process_frei0r_item( mlt_service_type type, double position , mlt_properties prop , mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ); +int process_frei0r_item( mlt_service_type, double position, mlt_properties, + mlt_frame, uint8_t **image, int *width, int *height ); void destruct (mlt_properties prop ); diff --git a/src/modules/frei0r/producer_frei0r.c b/src/modules/frei0r/producer_frei0r.c index ae1a26d8..0f16c862 100644 --- a/src/modules/frei0r/producer_frei0r.c +++ b/src/modules/frei0r/producer_frei0r.c @@ -37,7 +37,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); // Allocate the image - int size = *width * ( *height + 1 ) * 2; + int size = *width * ( *height + 1 ) * 4; // Allocate the image *buffer = mlt_pool_alloc( size ); @@ -47,14 +47,14 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form mlt_properties_set_int( properties, "width", *width ); mlt_properties_set_int( properties, "height", *height ); - *format = mlt_image_yuv422; + *format = mlt_image_rgb24a; if ( *buffer != NULL ) { mlt_position in = mlt_producer_get_in( producer ); mlt_position out = mlt_producer_get_out( producer ); mlt_position time = mlt_frame_get_position( frame ); double position = ( double )( time - in ) / ( double )( out - in + 1 ); - process_frei0r_item( producer_type , position, producer_props, frame , buffer, format , width , height , writable ); + process_frei0r_item( producer_type, position, producer_props, frame, buffer, width, height ); } return 0; diff --git a/src/modules/frei0r/transition_frei0r.c b/src/modules/frei0r/transition_frei0r.c index 4fb6846e..e9a75d8c 100644 --- a/src/modules/frei0r/transition_frei0r.c +++ b/src/modules/frei0r/transition_frei0r.c @@ -23,10 +23,6 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){ - if (*format!=mlt_image_yuv422 ){ - return -1; - } - mlt_frame b_frame = mlt_frame_pop_frame( a_frame ); mlt_transition transition = mlt_frame_pop_service( a_frame ); mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); @@ -50,8 +46,9 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f uint8_t *images[]={NULL,NULL,NULL}; - mlt_frame_get_image( a_frame, &images[0], format, width, height, 1 ); - mlt_frame_get_image( b_frame, &images[1], format, width, height, 1 ); + *format = mlt_image_rgb24a; + mlt_frame_get_image( a_frame, &images[0], format, width, height, 0 ); + mlt_frame_get_image( b_frame, &images[1], format, width, height, 0 ); mlt_position in = mlt_transition_get_in( transition ); mlt_position out = mlt_transition_get_out( transition ); @@ -62,7 +59,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f float pos=( float )( position - in ) / ( float )( out - in + 1 ); - process_frei0r_item( transition_type , pos , properties, !invert ? a_frame : b_frame , images , format, width,height, writable ); + process_frei0r_item( transition_type, pos, properties, !invert ? a_frame : b_frame, images, width, height ); *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" ); *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" ); diff --git a/src/modules/gtk2/filter_rescale.c b/src/modules/gtk2/filter_rescale.c index e3b6d17a..a6719267 100644 --- a/src/modules/gtk2/filter_rescale.c +++ b/src/modules/gtk2/filter_rescale.c @@ -29,7 +29,7 @@ #include #include -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 ); @@ -48,7 +48,9 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iform interp = PIXOPS_INTERP_HYPER; // Carry out the rescaling - if ( iformat == mlt_image_yuv422 && oformat == mlt_image_yuv422 ) + switch ( *format ) + { + case mlt_image_yuv422: { // Create the output image uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 ); @@ -66,67 +68,58 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iform // Return the output *image = output; + break; } - else if ( iformat == mlt_image_rgb24 || iformat == mlt_image_rgb24a ) + case mlt_image_rgb24: + case mlt_image_rgb24a: + case mlt_image_opengl: { - int bpp = (iformat == mlt_image_rgb24a ? 4 : 3 ); - - // Create the yuv image - uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 ); + int bpp = ( *format == mlt_image_rgb24 ? 3 : 4 ); + + // Create the output image + uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * bpp ); if ( strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) ) { GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( *image, GDK_COLORSPACE_RGB, - ( iformat == mlt_image_rgb24a ), 8, iwidth, iheight, + ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ), 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 + int src_stride = gdk_pixbuf_get_rowstride( scaled ); + int dst_stride = owidth * bpp; + if ( src_stride != dst_stride ) { - // 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( *image, owidth, oheight, owidth * 4, output, alpha ); - - mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL ); + int y = oheight; + uint8_t *src = gdk_pixbuf_get_pixels( scaled ); + uint8_t *dst = output; + while ( y-- ) + { + memcpy( dst, src, dst_stride ); + dst += dst_stride; + src += src_stride; + } } else { - // No alpha to extract - mlt_convert_rgb24_to_yuv422( *image, owidth, oheight, owidth * 3, output ); + memcpy( output, gdk_pixbuf_get_pixels( scaled ), owidth * oheight * bpp ); } - } - // Now update the frame - 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 ); + g_object_unref( scaled ); - *image = output; + // Now update the frame + mlt_properties_set_data( properties, "image", output, 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; + } + break; + } + default: + break; } return 0; diff --git a/src/modules/gtk2/producer_pango.c b/src/modules/gtk2/producer_pango.c index 3398e79a..1df06050 100644 --- a/src/modules/gtk2/producer_pango.c +++ b/src/modules/gtk2/producer_pango.c @@ -44,10 +44,9 @@ static pthread_mutex_t pango_mutex = PTHREAD_MUTEX_INITIALIZER; struct producer_pango_s { struct mlt_producer_s parent; - int width; - int height; - uint8_t *image; - uint8_t *alpha; + int width; + int height; + GdkPixbuf *pixbuf; char *fgcolor; char *bgcolor; int align; @@ -55,7 +54,7 @@ struct producer_pango_s char *markup; char *text; char *font; - int weight; + int weight; }; // special color type used by internal pango routines @@ -312,7 +311,7 @@ static int iconv_utf8( mlt_properties properties, const char *prop_name, const c static void refresh_image( mlt_frame frame, int width, int height ) { - // Pixbuf + // Pixbuf GdkPixbuf *pixbuf = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "pixbuf", NULL ); // Obtain properties of frame @@ -381,10 +380,9 @@ static void refresh_image( mlt_frame frame, int width, int height ) rgba_color fgcolor = parse_color( this->fgcolor ); rgba_color bgcolor = parse_color( this->bgcolor ); - mlt_pool_release( this->image ); - mlt_pool_release( this->alpha ); - this->image = NULL; - this->alpha = NULL; + if ( this->pixbuf ) + g_object_unref( this->pixbuf ); + this->pixbuf = NULL; // Convert from specified encoding to UTF-8 if ( encoding != NULL && !strncaseeq( encoding, "utf-8", 5 ) && !strncaseeq( encoding, "utf8", 4 ) ) @@ -419,13 +417,11 @@ static void refresh_image( mlt_frame frame, int width, int height ) this->height = gdk_pixbuf_get_height( pixbuf ); } } - else if ( pixbuf == NULL && ( width > 0 && ( this->image == NULL || width != this->width || height != this->height ) ) ) + else if ( pixbuf == NULL && width > 0 && ( this->pixbuf == NULL || width != this->width || height != this->height ) ) { - mlt_pool_release( this->image ); - mlt_pool_release( this->alpha ); - this->image = NULL; - this->alpha = NULL; - + if ( this->pixbuf ) + g_object_unref( this->pixbuf ); + this->pixbuf = NULL; pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL ); } @@ -445,24 +441,11 @@ static void refresh_image( mlt_frame frame, int width, int height ) // fprintf(stderr,"%s: scaling from %dx%d to %dx%d\n", __FILE__, this->width, this->height, width, height); // Note - the original pixbuf is already safe and ready for destruction - pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, interp ); + this->pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, interp ); // Store width and height this->width = width; this->height = height; - - // Allocate/define image - this->image = mlt_pool_alloc( width * ( height + 1 ) * 2 ); - this->alpha = mlt_pool_alloc( this->width * this->height ); - - // Convert the image - mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ), - this->width, this->height, - gdk_pixbuf_get_rowstride( pixbuf ), - this->image, this->alpha ); - - // Finished with pixbuf now - g_object_unref( pixbuf ); } // Set width/height @@ -470,24 +453,15 @@ static void refresh_image( mlt_frame frame, int width, int height ) mlt_properties_set_int( properties, "height", this->height ); mlt_properties_set_int( properties, "real_width", mlt_properties_get_int( producer_props, "real_width" ) ); mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "real_height" ) ); - - // pass the image data without destructor - mlt_properties_set_data( properties, "image", this->image, this->width * ( this->height + 1 ) * 2, NULL, NULL ); - mlt_properties_set_data( properties, "alpha", this->alpha, this->width * this->height, NULL, NULL ); } static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) { + producer_pango this = ( producer_pango ) mlt_frame_pop_service( frame ); + // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); - // We need to know the size of the image to clone it - int image_size = 0; - int alpha_size = 0; - - // Alpha channel - uint8_t *alpha = NULL; - *width = mlt_properties_get_int( properties, "rescale_width" ); *height = mlt_properties_get_int( properties, "rescale_height" ); @@ -495,43 +469,30 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form pthread_mutex_lock( &pango_mutex ); refresh_image( frame, *width, *height ); - // Get the image - *buffer = mlt_properties_get_data( properties, "image", &image_size ); - alpha = mlt_properties_get_data( properties, "alpha", &alpha_size ); - // Get width and height - *width = mlt_properties_get_int( properties, "width" ); - *height = mlt_properties_get_int( properties, "height" ); + *width = this->width; + *height = this->height; // Always clone here to allow 'animated' text - if ( *buffer != NULL ) + if ( this->pixbuf ) { - // Clone the image and the alpha - uint8_t *image_copy = mlt_pool_alloc( image_size ); - uint8_t *alpha_copy = mlt_pool_alloc( alpha_size ); - - memcpy( image_copy, *buffer, image_size ); - - // Copy or default the alpha - if ( alpha != NULL ) - memcpy( alpha_copy, alpha, alpha_size ); - else - memset( alpha_copy, 255, alpha_size ); + // Clone the image + int image_size = this->width * this->height * 4; + *buffer = mlt_pool_alloc( image_size ); + memcpy( *buffer, gdk_pixbuf_get_pixels( this->pixbuf ), image_size ); // Now update properties so we free the copy after - mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); - mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL ); - - // We're going to pass the copy on - *buffer = image_copy; + mlt_properties_set_data( properties, "image", *buffer, image_size, mlt_pool_release, NULL ); + *format = mlt_image_rgb24a; } else { // TODO: Review all cases of invalid images *buffer = mlt_pool_alloc( 50 * 50 * 2 ); - mlt_properties_set_data( properties, "image", *buffer, image_size, mlt_pool_release, NULL ); + mlt_properties_set_data( properties, "image", *buffer, 50 * 50 * 2, mlt_pool_release, NULL ); *width = 50; *height = 50; + *format = mlt_image_yuv422; } pthread_mutex_unlock( &pango_mutex ); @@ -539,15 +500,6 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form 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 ); -} - static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { producer_pango this = producer->child; @@ -574,10 +526,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_properties_set_int( properties, "progressive", 1 ); mlt_properties_set_double( properties, "aspect_ratio", 1 ); - // Set alpha call back - ( *frame )->get_alpha_mask = producer_get_alpha_mask; - // Stack the get image callback + mlt_frame_push_service( *frame, this ); mlt_frame_push_get_image( *frame, producer_get_image ); // Calculate the next timecode @@ -589,8 +539,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i static void producer_close( mlt_producer parent ) { producer_pango this = parent->child; - mlt_pool_release( this->image ); - mlt_pool_release( this->alpha ); + if ( this->pixbuf ) + g_object_unref( this->pixbuf ); free( this->fgcolor ); free( this->bgcolor ); free( this->markup ); diff --git a/src/modules/gtk2/producer_pixbuf.c b/src/modules/gtk2/producer_pixbuf.c index b72e9c82..e9395ec9 100644 --- a/src/modules/gtk2/producer_pixbuf.c +++ b/src/modules/gtk2/producer_pixbuf.c @@ -49,10 +49,9 @@ struct producer_pixbuf_s int pixbuf_idx; int width; int height; + int alpha; uint8_t *image; - uint8_t *alpha; mlt_cache_item image_cache; - mlt_cache_item alpha_cache; pthread_mutex_t mutex; }; @@ -217,10 +216,6 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int this->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" ); this->image = mlt_cache_item_data( this->image_cache, NULL ); - // restore alpha channel - this->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" ); - this->alpha = mlt_cache_item_data( this->alpha_cache, NULL ); - // Check if user wants us to reload the image if ( mlt_properties_get_int( producer_props, "force_reload" ) ) { @@ -265,7 +260,7 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int mlt_properties_set_int( producer_props, "_real_width", mlt_properties_get_int( cached_props, "real_width" ) ); mlt_properties_set_int( producer_props, "_real_height", mlt_properties_get_int( cached_props, "real_height" ) ); this->image = mlt_properties_get_data( cached_props, "image", NULL ); - this->alpha = mlt_properties_get_data( cached_props, "alpha", NULL ); + this->alpha = mlt_properties_get_int( cached_props, "alpha" ); if ( width != 0 && ( width != this->width || height != this->height ) ) this->image = NULL; @@ -324,37 +319,33 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int this->height = height; // Allocate/define image - this->image = mlt_pool_alloc( width * ( height + 1 ) * 2 ); - if ( !use_cache ) - mlt_cache_item_close( this->image_cache ); - mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image", this->image, width * ( height + 1 ) * 2, mlt_pool_release ); - this->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" ); - this->image_idx = image_idx; + this->alpha = gdk_pixbuf_get_has_alpha( pixbuf ); + int src_stride = gdk_pixbuf_get_rowstride( pixbuf ); + int dst_stride = this->width * ( this->alpha ? 4 : 3 ); + int image_size = dst_stride * ( height + 1 ); + this->image = mlt_pool_alloc( image_size ); - // Extract YUV422 and alpha - if ( gdk_pixbuf_get_has_alpha( pixbuf ) ) + if ( src_stride != dst_stride ) { - // Allocate the alpha mask - this->alpha = mlt_pool_alloc( this->width * this->height ); - if ( !use_cache ) - mlt_cache_item_close( this->alpha_cache ); - mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha", this->alpha, width * height, mlt_pool_release ); - this->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" ); - - // Convert the image - mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ), - this->width, this->height, - gdk_pixbuf_get_rowstride( pixbuf ), - this->image, this->alpha ); + int y = this->height; + uint8_t *src = gdk_pixbuf_get_pixels( pixbuf ); + uint8_t *dst = this->image; + while ( y-- ) + { + memcpy( dst, src, dst_stride ); + dst += dst_stride; + src += src_stride; + } } else - { - // No alpha to extract - mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ), - this->width, this->height, - gdk_pixbuf_get_rowstride( pixbuf ), - this->image ); + { + memcpy( this->image, gdk_pixbuf_get_pixels( pixbuf ), src_stride * height ); } + if ( !use_cache ) + mlt_cache_item_close( this->image_cache ); + mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image", this->image, image_size, mlt_pool_release ); + this->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" ); + this->image_idx = image_idx; // Finished with pixbuf now g_object_unref( pixbuf ); @@ -369,7 +360,6 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int { pthread_mutex_unlock( &this->mutex ); mlt_cache_item_close( this->image_cache ); - mlt_cache_item_close( this->alpha_cache ); } // Set width/height of frame @@ -386,8 +376,8 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int mlt_properties_set_int( cached_props, "height", this->height ); mlt_properties_set_int( cached_props, "real_width", mlt_properties_get_int( producer_props, "_real_width" ) ); mlt_properties_set_int( cached_props, "real_height", mlt_properties_get_int( producer_props, "_real_height" ) ); - mlt_properties_set_data( cached_props, "image", this->image, this->width * ( this->height + 1 ) * 2, mlt_pool_release, NULL ); - mlt_properties_set_data( cached_props, "alpha", this->alpha, this->width * this->height, mlt_pool_release, NULL ); + mlt_properties_set_data( cached_props, "image", this->image, this->width * ( this->alpha ? 4 : 3 ) * this->height, mlt_pool_release, NULL ); + mlt_properties_set_int( cached_props, "alpha", this->alpha ); mlt_properties_set_data( cache, image_key, cached, 0, ( mlt_destructor )mlt_frame_close, NULL ); } @@ -408,84 +398,43 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form // Refresh the image refresh_image( this, frame, *width, *height ); - // Get the image size - int image_size = this->width * ( this->height + 1 ) * 2; - int alpha_size = this->width * this->height; - // Get width and height (may have changed during the refresh) - *width = mlt_properties_get_int( properties, "width" ); - *height = mlt_properties_get_int( properties, "height" ); + *width = this->width; + *height = this->height; // NB: Cloning is necessary with this producer (due to processing of images ahead of use) // The fault is not in the design of mlt, but in the implementation of the pixbuf producer... if ( this->image ) { - if ( *format == mlt_image_yuv422 || *format == mlt_image_yuv420p ) - { - // Clone the image and the alpha - uint8_t *image_copy = mlt_pool_alloc( image_size ); - uint8_t *alpha_copy = mlt_pool_alloc( alpha_size ); - - memcpy( image_copy, this->image, image_size ); - - // Copy or default the alpha - if ( this->alpha != NULL ) - memcpy( alpha_copy, this->alpha, alpha_size ); - else - memset( alpha_copy, 255, alpha_size ); - - // Now update properties so we free the copy after - mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); - mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL ); - - // We're going to pass the copy on - *buffer = image_copy; - } - else if ( *format == mlt_image_rgb24a ) - { - // Clone the image and the alpha - image_size = *width * ( *height + 1 ) * 4; - alpha_size = *width * ( *height + 1 ); - uint8_t *image_copy = mlt_pool_alloc( image_size ); - uint8_t *alpha_copy = mlt_pool_alloc( alpha_size ); - - mlt_convert_yuv422_to_rgb24a( this->image, image_copy, (*width)*(*height) ); - - // Now update properties so we free the copy after - mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); - mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL ); - - // We're going to pass the copy on - *buffer = image_copy; - } - + // Clone the image + int image_size = this->width * this->height * ( this->alpha ? 4 :3 ); + uint8_t *image_copy = mlt_pool_alloc( image_size ); + memcpy( image_copy, this->image, image_size ); + // Now update properties so we free the copy after + mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); + // We're going to pass the copy on + *buffer = image_copy; + *format = this->alpha ? mlt_image_rgb24a : mlt_image_rgb24; + mlt_log_debug( MLT_PRODUCER_SERVICE( &this->parent ), "%dx%d (%s)\n", + this->width, this->height, mlt_image_format_name( *format ) ); } else { // TODO: Review all cases of invalid images *buffer = mlt_pool_alloc( 50 * 50 * 2 ); - mlt_properties_set_data( properties, "image", *buffer, image_size, mlt_pool_release, NULL ); + mlt_properties_set_data( properties, "image", *buffer, 50 * 50 * 2, mlt_pool_release, NULL ); *width = 50; *height = 50; + *format = mlt_image_yuv422; } // Release references and locks pthread_mutex_unlock( &this->mutex ); mlt_cache_item_close( this->image_cache ); - mlt_cache_item_close( this->alpha_cache ); 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 ); -} - static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { // Get the real structure for this producer @@ -521,9 +470,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( producer_properties, "progressive" ) ); mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_properties, "aspect_ratio" ) ); - // Set alpha call back - ( *frame )->get_alpha_mask = producer_get_alpha_mask; - // Push the get_image method mlt_frame_push_get_image( *frame, producer_get_image ); } diff --git a/src/modules/kdenlive/filter_boxblur.c b/src/modules/kdenlive/filter_boxblur.c index f1d54259..ab318df3 100644 --- a/src/modules/kdenlive/filter_boxblur.c +++ b/src/modules/kdenlive/filter_boxblur.c @@ -163,12 +163,13 @@ static void DoBoxBlur(uint8_t *yuv, int32_t *rgb, unsigned int width, unsigned i static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the image + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); short hori = mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "hori" ); short vert = mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "vert" ); // Only process if we have no error and a valid colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { double factor = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "boxblur" ); if (factor != 0) { @@ -178,7 +179,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * DoBoxBlur (*image, rgb, *width, h, (int) factor*hori, (int) factor*vert); mlt_pool_release (rgb); } - } + } return error; } diff --git a/src/modules/kdenlive/filter_wave.c b/src/modules/kdenlive/filter_wave.c index d01944f1..1cb27dd3 100644 --- a/src/modules/kdenlive/filter_wave.c +++ b/src/modules/kdenlive/filter_wave.c @@ -63,24 +63,24 @@ static void DoWave(uint8_t *src, int src_w, int src_h, uint8_t *dst, mlt_positio static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the image - int error = mlt_frame_get_image( this, image, format, width, height, 1 ); + *format = mlt_image_yuv422; + int error = mlt_frame_get_image( this, image, format, width, height, 0 ); mlt_position position = mlt_frame_get_position( this ); // Only process if we have no error and a valid colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { double factor = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "wave" ); int speed = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "speed" ); - int deformX = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformX" ); - int deformY = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformY" ); - if (factor != 0) { + int deformX = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformX" ); + int deformY = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformY" ); + if (factor != 0) { int image_size = *width * (*height + 1) * 2; - uint8_t *dest = mlt_pool_alloc (image_size); - DoWave(*image, *width, (*height + 1), dest, position, speed, factor, deformX, deformY); - memcpy(*image, dest, image_size); - mlt_pool_release(dest); - } - } + *image = mlt_pool_alloc (image_size); + DoWave(*image, *width, (*height + 1), *image, position, speed, factor, deformX, deformY); + mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", *image, image_size, mlt_pool_release, NULL ); + } + } return error; } diff --git a/src/modules/kdenlive/producer_framebuffer.c b/src/modules/kdenlive/producer_framebuffer.c index a96ca3a7..0249a443 100644 --- a/src/modules/kdenlive/producer_framebuffer.c +++ b/src/modules/kdenlive/producer_framebuffer.c @@ -116,6 +116,9 @@ static int framebuffer_get_image( mlt_frame this, uint8_t **image, mlt_image_for case mlt_image_rgb24: size = *width * ( *height + 1 ) * 3; break; + case mlt_image_rgb24a: + size = *width * ( *height + 1 ) * 4; + break; default: *format = mlt_image_yuv422; size = *width * ( *height + 1 ) * 2; @@ -133,7 +136,7 @@ static int framebuffer_get_image( mlt_frame this, uint8_t **image, mlt_image_for } // Which frames are buffered? - uint8_t *first_image = mlt_properties_get_data( first_frame_properties, "image", NULL ); + uint8_t *first_image = mlt_properties_get_data( first_frame_properties, "image", &size ); if( first_image == NULL ) { mlt_properties props = MLT_FRAME_PROPERTIES( this ); diff --git a/src/modules/motion_est/filter_crop_detect.c b/src/modules/motion_est/filter_crop_detect.c index 8165141a..c1f91071 100644 --- a/src/modules/motion_est/filter_crop_detect.c +++ b/src/modules/motion_est/filter_crop_detect.c @@ -87,17 +87,9 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * // There is no way to detect a crop for sure, so make up an arbitrary one int thresh = mlt_properties_get_int( properties, "thresh" ); - int xstride, ystride; - - switch( *format ) { - case mlt_image_yuv422: - xstride = 2; - ystride = 2 * *width; - break; - default: - fprintf(stderr, "image format not supported by filter_crop_detect\n"); - return -1; - } + *format = mlt_image_yuv422; + int xstride = 2; + int ystride = 2 * *width; int x, y, average_brightness, deviation; // Scratch variables uint8_t *q; diff --git a/src/modules/motion_est/filter_motion_est.c b/src/modules/motion_est/filter_motion_est.c index 6e8b0218..25cfe524 100644 --- a/src/modules/motion_est/filter_motion_est.c +++ b/src/modules/motion_est/filter_motion_est.c @@ -787,6 +787,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format // Get the new image and frame number + *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); #ifdef BENCHMARK @@ -869,17 +870,8 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format c->former_vectors_valid = 0; memset( c->former_vectors, 0, c->mv_size ); - // Calculate the size of our steps (the number of bytes that seperate adjacent pixels in X and Y direction) - switch( *format ) { - case mlt_image_yuv422: - c->xstride = 2; - c->ystride = c->xstride * *width; - break; - default: - // I don't know - fprintf(stderr, "\"I am unfamiliar with your new fangled pixel format!\" -filter_motion_est\n"); - return -1; - } + c->xstride = 2; + c->ystride = c->xstride * *width; // Allocate a cache for the previous frame's image c->former_image = mlt_pool_alloc( *width * *height * 2 ); diff --git a/src/modules/motion_est/filter_vismv.c b/src/modules/motion_est/filter_vismv.c index eb0d9870..90de5e13 100644 --- a/src/modules/motion_est/filter_vismv.c +++ b/src/modules/motion_est/filter_vismv.c @@ -75,6 +75,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format mlt_properties properties = MLT_FRAME_PROPERTIES(frame); // Get the new image + *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); if( error != 0 ) diff --git a/src/modules/motion_est/producer_slowmotion.c b/src/modules/motion_est/producer_slowmotion.c index 016b5d59..d08d4b55 100644 --- a/src/modules/motion_est/producer_slowmotion.c +++ b/src/modules/motion_est/producer_slowmotion.c @@ -163,17 +163,10 @@ static int slowmotion_get_image( mlt_frame this, uint8_t **image, mlt_image_form mlt_properties second_frame_properties = MLT_FRAME_PROPERTIES( second_frame ); // image stride - int size, xstride, ystride; - switch( *format ){ - case mlt_image_yuv422: - size = *width * *height * 2; - xstride = 2; - ystride = 2 * *width; - break; - default: - fprintf(stderr, "Unsupported image format\n"); - return -1; - } + *format = mlt_image_yuv422; + int size = *width * *height * 2; + int xstride = 2; + int ystride = 2 * *width; uint8_t *output = mlt_properties_get_data( producer_properties, "output_buffer", 0 ); if( output == NULL ) diff --git a/src/modules/oldfilm/filter_dust.c b/src/modules/oldfilm/filter_dust.c index fc62024f..140b759d 100644 --- a/src/modules/oldfilm/filter_dust.c +++ b/src/modules/oldfilm/filter_dust.c @@ -70,7 +70,8 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * mlt_position out = mlt_filter_get_out( filter ); mlt_position time = mlt_frame_get_position( this ); double position = ( double )( time - in ) / ( double )( out - in + 1 ); - + + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); // load svg mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); @@ -156,7 +157,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * } if (piccount>0 ) return 0; - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { int h = *height; diff --git a/src/modules/oldfilm/filter_grain.c b/src/modules/oldfilm/filter_grain.c index 296da5a8..1095d1a1 100644 --- a/src/modules/oldfilm/filter_grain.c +++ b/src/modules/oldfilm/filter_grain.c @@ -30,9 +30,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * { mlt_filter filter = mlt_frame_pop_service( this ); + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { int h = *height; int w = *width; diff --git a/src/modules/oldfilm/filter_lines.c b/src/modules/oldfilm/filter_lines.c index 7d3e415e..bd77c239 100644 --- a/src/modules/oldfilm/filter_lines.c +++ b/src/modules/oldfilm/filter_lines.c @@ -28,9 +28,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * { mlt_filter filter = mlt_frame_pop_service( this ); + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { int h = *height; int w = *width; diff --git a/src/modules/oldfilm/filter_oldfilm.c b/src/modules/oldfilm/filter_oldfilm.c index 11a6c3e9..398aa44b 100644 --- a/src/modules/oldfilm/filter_oldfilm.c +++ b/src/modules/oldfilm/filter_oldfilm.c @@ -29,9 +29,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * { mlt_filter filter = mlt_frame_pop_service( this ); + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { int h = *height; int w = *width; diff --git a/src/modules/oldfilm/filter_tcolor.c b/src/modules/oldfilm/filter_tcolor.c index 824f107e..86b2bbcc 100644 --- a/src/modules/oldfilm/filter_tcolor.c +++ b/src/modules/oldfilm/filter_tcolor.c @@ -31,9 +31,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * { mlt_filter filter = mlt_frame_pop_service( this ); + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { double over_cr = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "oversaturate_cr" )/100.0; diff --git a/src/modules/oldfilm/filter_vignette.c b/src/modules/oldfilm/filter_vignette.c index e9e3f5d0..2788470e 100644 --- a/src/modules/oldfilm/filter_vignette.c +++ b/src/modules/oldfilm/filter_vignette.c @@ -35,9 +35,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * { mlt_filter filter = mlt_frame_pop_service( this ); + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { mlt_position in = mlt_filter_get_in( filter ); //mlt_position out = mlt_filter_get_out( filter ); diff --git a/src/modules/plus/filter_affine.c b/src/modules/plus/filter_affine.c index 0ba2f9d5..1c05fbd6 100644 --- a/src/modules/plus/filter_affine.c +++ b/src/modules/plus/filter_affine.c @@ -37,10 +37,12 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); // Get the image - int error = 0; //mlt_frame_get_image( this, image, format, width, height, 0 ); + int error = 0; + *format = mlt_image_yuv422; + //mlt_frame_get_image( this, image, format, width, height, 0 ); // Only process if we have no error and a valid colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL ); mlt_transition transition = mlt_properties_get_data( properties, "transition", NULL ); diff --git a/src/modules/plus/filter_charcoal.c b/src/modules/plus/filter_charcoal.c index e99981a5..3c7c22cd 100644 --- a/src/modules/plus/filter_charcoal.c +++ b/src/modules/plus/filter_charcoal.c @@ -72,10 +72,11 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * mlt_filter filter = mlt_frame_pop_service( this ); // Get the image + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); // Only process if we have no error and a valid colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { // Get the charcoal scatter value int x_scatter = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "x_scatter" ); diff --git a/src/modules/plus/filter_invert.c b/src/modules/plus/filter_invert.c index 4385fc86..f2830739 100644 --- a/src/modules/plus/filter_invert.c +++ b/src/modules/plus/filter_invert.c @@ -39,10 +39,11 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * // Get the image mlt_filter filter = mlt_frame_pop_service( this ); int mask = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "alpha" ); + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); // Only process if we have no error and a valid colour space - if ( error == 0 && *format == mlt_image_yuv422 ) + if ( error == 0 ) { uint8_t *p = *image; uint8_t *q = *image + *width * *height * 2; diff --git a/src/modules/plus/filter_sepia.c b/src/modules/plus/filter_sepia.c index aa20b23a..bb675651 100644 --- a/src/modules/plus/filter_sepia.c +++ b/src/modules/plus/filter_sepia.c @@ -34,10 +34,11 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * mlt_filter filter = mlt_frame_pop_service( this ); // Get the image + *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); // Only process if we have no error and a valid colour space - if ( error == 0 && *image && *format == mlt_image_yuv422 ) + if ( error == 0 && *image ) { // We modify the whole image uint8_t *p = *image; diff --git a/src/modules/plus/transition_affine.c b/src/modules/plus/transition_affine.c index 71970561..a9a813da 100644 --- a/src/modules/plus/transition_affine.c +++ b/src/modules/plus/transition_affine.c @@ -401,6 +401,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f position = abs( position - length ); // Fetch the a frame image + *format = mlt_image_yuv422; mlt_frame_get_image( a_frame, image, format, width, height, 1 ); // Calculate the region now diff --git a/src/modules/qimage/producer_qimage.c b/src/modules/qimage/producer_qimage.c index d2af3677..bf7db6fe 100644 --- a/src/modules/qimage/producer_qimage.c +++ b/src/modules/qimage/producer_qimage.c @@ -184,83 +184,43 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form // Refresh the image refresh_qimage( this, frame, *width, *height ); - // We need to know the size of the image to clone it - int image_size = this->current_width * ( this->current_height + 1 ) * 2; - int alpha_size = this->current_width * this->current_height; - // Get width and height (may have changed during the refresh) *width = mlt_properties_get_int( properties, "width" ); *height = mlt_properties_get_int( properties, "height" ); // NB: Cloning is necessary with this producer (due to processing of images ahead of use) // The fault is not in the design of mlt, but in the implementation of the qimage producer... - if ( this->current_image != NULL ) + if ( this->current_image ) { - if ( *format == mlt_image_yuv422 || *format == mlt_image_yuv420p ) - { - // Clone the image and the alpha - uint8_t *image_copy = mlt_pool_alloc( image_size ); - uint8_t *alpha_copy = mlt_pool_alloc( alpha_size ); - - memcpy( image_copy, this->current_image, image_size ); - - // Copy or default the alpha - if ( this->current_alpha ) - memcpy( alpha_copy, this->current_alpha, alpha_size ); - else - memset( alpha_copy, 255, alpha_size ); - - // Now update properties so we free the copy after - mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); - mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL ); - - // We're going to pass the copy on - *buffer = image_copy; - } - else if ( *format == mlt_image_rgb24a ) - { - // Clone the image and the alpha - image_size = *width * ( *height + 1 ) * 4; - alpha_size = *width * ( *height + 1 ); - uint8_t *image_copy = mlt_pool_alloc( image_size ); - uint8_t *alpha_copy = mlt_pool_alloc( alpha_size ); - - mlt_convert_yuv422_to_rgb24a(this->current_image, image_copy, (*width)*(*height)); - - // Now update properties so we free the copy after - mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); - mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL ); - - // We're going to pass the copy on - *buffer = image_copy; - } + // Clone the image and the alpha + int image_size = this->current_width * ( this->current_height + 1 ) * ( this->has_alpha ? 4 :3 ); + uint8_t *image_copy = mlt_pool_alloc( image_size ); + memcpy( image_copy, this->current_image, image_size ); + // Now update properties so we free the copy after + mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL ); + // We're going to pass the copy on + *buffer = image_copy; + *format = this->has_alpha ? mlt_image_rgb24a : mlt_image_rgb24; + mlt_log_debug( MLT_PRODUCER_SERVICE( &this->parent ), "%dx%d (%s)\n", + this->current_width, this->current_height, mlt_image_format_name( *format ) ); } else { // TODO: Review all cases of invalid images *buffer = mlt_pool_alloc( 50 * 50 * 2 ); - mlt_properties_set_data( properties, "image", *buffer, image_size, mlt_pool_release, NULL ); + mlt_properties_set_data( properties, "image", *buffer, 50 * 50 * 2, mlt_pool_release, NULL ); *width = 50; *height = 50; + *format = mlt_image_yuv422; } // Release references and locks pthread_mutex_unlock( &this->mutex ); mlt_cache_item_close( this->image_cache ); - mlt_cache_item_close( this->alpha_cache ); 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 ); -} - static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { // Get the real structure for this producer @@ -296,9 +256,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( producer_properties, "progressive" ) ); mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_properties, "aspect_ratio" ) ); - // Set alpha call back - ( *frame )->get_alpha_mask = producer_get_alpha_mask; - // Push the get_image method mlt_frame_push_get_image( *frame, producer_get_image ); } diff --git a/src/modules/qimage/qimage_wrapper.cpp b/src/modules/qimage/qimage_wrapper.cpp index 6c038f64..ed52681c 100644 --- a/src/modules/qimage/qimage_wrapper.cpp +++ b/src/modules/qimage/qimage_wrapper.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #endif @@ -96,10 +97,6 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" ); self->current_image = static_cast( mlt_cache_item_data( self->image_cache, NULL ) ); - // restore alpha channel - self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" ); - self->current_alpha = static_cast( mlt_cache_item_data( self->alpha_cache, NULL ) ); - // Check if user wants us to reload the image if ( mlt_properties_get_int( producer_props, "force_reload" ) ) { @@ -149,7 +146,7 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh mlt_properties_set_int( producer_props, "_real_width", mlt_properties_get_int( cached_props, "real_width" ) ); mlt_properties_set_int( producer_props, "_real_height", mlt_properties_get_int( cached_props, "real_height" ) ); self->current_image = ( uint8_t * )mlt_properties_get_data( cached_props, "image", NULL ); - self->current_alpha = ( uint8_t * )mlt_properties_get_data( cached_props, "alpha", NULL ); + self->has_alpha = mlt_properties_get_int( cached_props, "alpha" ); if ( width != 0 && ( width != self->current_width || height != self->current_height ) ) self->current_image = NULL; @@ -204,61 +201,52 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh #ifdef USE_QT4 // Note - the original qimage is already safe and ready for destruction - QImage scaled = interp == 0 ? qimage->scaled( QSize( width, height)) : qimage->scaled( QSize(width, height), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + QImage scaled = interp == 0 ? qimage->scaled( QSize( width, height ) ) : + qimage->scaled( QSize(width, height), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); QImage temp; - bool hasAlpha = scaled.hasAlphaChannel(); - if (hasAlpha) - temp = scaled.convertToFormat(QImage::Format_ARGB32); - else - temp = scaled.convertToFormat(QImage::Format_RGB888); + self->has_alpha = scaled.hasAlphaChannel(); #endif #ifdef USE_QT3 // Note - the original qimage is already safe and ready for destruction - QImage scaled = interp == 0 ? qimage->scale( width, height, QImage::ScaleFree ) : qimage->smoothScale( width, height, QImage::ScaleFree ); - QImage temp = scaled.convertDepth( 32 ); - bool hasAlpha = true; + QImage scaled = interp == 0 ? qimage->scale( width, height, QImage::ScaleFree ) : + qimage->smoothScale( width, height, QImage::ScaleFree ); + self->has_alpha = 1; #endif // Store width and height self->current_width = width; self->current_height = height; - + // Allocate/define image - self->current_image = ( uint8_t * )mlt_pool_alloc( width * ( height + 1 ) * 2 ); + int dst_stride = width * ( self->has_alpha ? 4 : 3 ); + int image_size = dst_stride * ( height + 1 ); + self->current_image = ( uint8_t * )mlt_pool_alloc( image_size ); + + // Copy the image + int y = self->current_height + 1; + uint8_t *dst = self->current_image; + while ( --y ) + { + QRgb *src = (QRgb*) scaled.scanLine( self->current_height - y ); + int x = self->current_width + 1; + while ( --x ) + { + *dst++ = qRed(*src); + *dst++ = qGreen(*src); + *dst++ = qBlue(*src); + if ( self->has_alpha ) *dst++ = qAlpha(*src); + ++src; + } + } + + // Update the cache if ( !use_cache ) mlt_cache_item_close( self->image_cache ); - mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.image", self->current_image, width * ( height + 1 ) * 2, mlt_pool_release ); + mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.image", self->current_image, image_size, mlt_pool_release ); self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" ); self->image_idx = image_idx; - if (!hasAlpha) { - mlt_convert_rgb24_to_yuv422( temp.bits(), self->current_width, self->current_height, temp.bytesPerLine(), self->current_image ); - } - else { - // Allocate the alpha mask - self->current_alpha = ( uint8_t * )mlt_pool_alloc( width * height ); - if ( !use_cache ) - mlt_cache_item_close( self->alpha_cache ); - mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha", self->current_alpha, width * height, mlt_pool_release ); - self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" ); - -#ifdef USE_QT4 - if ( QSysInfo::ByteOrder == QSysInfo::BigEndian ) - mlt_convert_argb_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine(), self->current_image, self->current_alpha ); - else - mlt_convert_bgr24a_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine( ), self->current_image, self->current_alpha ); -#endif - -#ifdef USE_QT3 - // Convert the image - if ( QImage::systemByteOrder( ) == QImage::BigEndian ) - mlt_convert_argb_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine( ), self->current_image, self->current_alpha ); - else - mlt_convert_bgr24a_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine( ), self->current_image, self->current_alpha ); -#endif - } - // Ensure we update the cache when we need to update_cache = use_cache; } @@ -269,7 +257,6 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh { pthread_mutex_unlock( &self->mutex ); mlt_cache_item_close( self->image_cache ); - mlt_cache_item_close( self->alpha_cache ); } // Set width/height of frame @@ -286,8 +273,10 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh mlt_properties_set_int( cached_props, "height", self->current_height ); mlt_properties_set_int( cached_props, "real_width", mlt_properties_get_int( producer_props, "_real_width" ) ); mlt_properties_set_int( cached_props, "real_height", mlt_properties_get_int( producer_props, "_real_height" ) ); - mlt_properties_set_data( cached_props, "image", self->current_image, self->current_width * ( self->current_height + 1 ) * 2, mlt_pool_release, NULL ); - mlt_properties_set_data( cached_props, "alpha", self->current_alpha, self->current_width * self->current_height, mlt_pool_release, NULL ); + mlt_properties_set_data( cached_props, "image", self->current_image, + self->current_width * ( self->current_height + 1 ) * ( self->has_alpha ? 4 : 3 ), + mlt_pool_release, NULL ); + mlt_properties_set_int( cached_props, "alpha", self->has_alpha ); mlt_properties_set_data( cache, image_key, cached, 0, ( mlt_destructor )mlt_frame_close, NULL ); } g_mutex.unlock(); diff --git a/src/modules/qimage/qimage_wrapper.h b/src/modules/qimage/qimage_wrapper.h index c87b1930..22b1110b 100644 --- a/src/modules/qimage/qimage_wrapper.h +++ b/src/modules/qimage/qimage_wrapper.h @@ -41,11 +41,10 @@ struct producer_qimage_s int image_idx; int qimage_idx; uint8_t *current_image; - uint8_t *current_alpha; + int has_alpha; int current_width; int current_height; mlt_cache_item image_cache; - mlt_cache_item alpha_cache; pthread_mutex_t mutex; }; diff --git a/src/modules/sdl/consumer_sdl.c b/src/modules/sdl/consumer_sdl.c index 38322370..13c4a0c2 100644 --- a/src/modules/sdl/consumer_sdl.c +++ b/src/modules/sdl/consumer_sdl.c @@ -64,7 +64,6 @@ struct consumer_sdl_s SDL_Rect rect; uint8_t *buffer; int bpp; - int filtered; }; /** Forward references to static functions. @@ -183,20 +182,6 @@ int consumer_start( mlt_consumer parent ) this->bpp = mlt_properties_get_int( this->properties, "bpp" ); - // Attach a colour space converter - if ( preview_off && !this->filtered ) - { - mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( parent ) ); - mlt_filter filter = mlt_factory_filter( profile, "avcolour_space", NULL ); - if ( filter ) - { - mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "forced", mlt_image_yuv422 ); - mlt_service_attach( MLT_CONSUMER_SERVICE( parent ), filter ); - mlt_filter_close( filter ); - } - this->filtered = 1; - } - if ( sdl_started == 0 && display_off == 0 ) { if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) diff --git a/src/modules/sdl/consumer_sdl_still.c b/src/modules/sdl/consumer_sdl_still.c index 3efd8f4e..755dd9ac 100644 --- a/src/modules/sdl/consumer_sdl_still.c +++ b/src/modules/sdl/consumer_sdl_still.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -54,7 +55,6 @@ struct consumer_sdl_s uint8_t *buffer; int last_position; mlt_producer last_producer; - int filtered; }; /** Forward references to static functions. @@ -96,9 +96,6 @@ mlt_consumer consumer_sdl_still_init( mlt_profile profile, mlt_service_type type // We're always going to run this in non-realtime mode mlt_properties_set( this->properties, "real_time", "0" ); - // Default progressive true - mlt_properties_set_int( this->properties, "progressive", 1 ); - // Ensure we don't join on a non-running object this->joined = 1; @@ -151,17 +148,6 @@ static int consumer_start( mlt_consumer parent ) int preview_off = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "preview_off" ); int sdl_started = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "sdl_started" ); - // Attach a colour space converter - if ( !this->filtered ) - { - mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( parent ) ); - mlt_filter filter = mlt_factory_filter( profile, "avcolour_space", NULL ); - mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "forced", mlt_image_yuv422 ); - mlt_service_attach( MLT_CONSUMER_SERVICE( parent ), filter ); - mlt_filter_close( filter ); - this->filtered = 1; - } - consumer_stop( parent ); this->last_position = -1; @@ -439,23 +425,21 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame ) SDL_FillRect( this->sdl_screen, NULL, color >> 8 ); changed = 1; } - else - { - changed = 1; - } if ( changed == 0 && this->last_position == mlt_frame_get_position( frame ) && - this->last_producer == mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "_producer", NULL ) ) + this->last_producer == mlt_frame_get_original_producer( frame ) ) { sdl_unlock_display( ); if ( unlock != NULL ) unlock( ); + struct timespec tm = { 0, 100000 }; + nanosleep( &tm, NULL ); return 0; } // Update last frame shown info this->last_position = mlt_frame_get_position( frame ); - this->last_producer = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "_producer", NULL ); + this->last_producer = mlt_frame_get_original_producer( frame ); // Get the image, width and height mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 ); @@ -539,21 +523,10 @@ static void *consumer_thread( void *arg ) // Get the consumer mlt_consumer consumer = &this->parent; mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); - - // internal intialization mlt_frame frame = NULL; - mlt_image_format vfmt = mlt_image_rgb24a; - int height = this->height; - int width = this->width; - uint8_t *image = NULL; // Allow the hosting app to provide the preview int preview_off = mlt_properties_get_int( properties, "preview_off" ); - mlt_image_format preview_format = mlt_properties_get_int( properties, "preview_format" ); - - // Check if a specific colour space has been requested - if ( preview_off && preview_format != mlt_image_none ) - vfmt = preview_format; // Loop until told not to while( this->running ) @@ -570,6 +543,16 @@ static void *consumer_thread( void *arg ) } else { + mlt_image_format vfmt = mlt_image_rgb24a; + int height = this->height; + int width = this->width; + uint8_t *image = NULL; + mlt_image_format preview_format = mlt_properties_get_int( properties, "preview_format" ); + + // Check if a specific colour space has been requested + if ( preview_off && preview_format != mlt_image_none ) + vfmt = preview_format; + mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "format", vfmt ); mlt_events_fire( properties, "consumer-frame-show", frame, NULL ); diff --git a/src/modules/sdl/producer_sdl_image.c b/src/modules/sdl/producer_sdl_image.c index 19f4f4b0..0d624664 100644 --- a/src/modules/sdl/producer_sdl_image.c +++ b/src/modules/sdl/producer_sdl_image.c @@ -38,13 +38,10 @@ static int producer_get_image( mlt_frame frame, uint8_t **image, mlt_image_forma mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); SDL_Surface *surface = mlt_properties_get_data( properties, "surface", NULL ); SDL_Surface *converted = NULL; - uint8_t *alpha; *width = surface->w; *height = surface->h; - *format = mlt_image_yuv422; - *image = mlt_pool_alloc( *width * *height * 2 ); - alpha = mlt_pool_alloc( *width * *height ); + int image_size = *width * *height * 3; if ( surface->format->BitsPerPixel != 32 && surface->format->BitsPerPixel != 24 ) { @@ -63,15 +60,19 @@ static int producer_get_image( mlt_frame frame, uint8_t **image, mlt_image_forma switch( surface->format->BitsPerPixel ) { case 32: - mlt_convert_rgb24a_to_yuv422( surface->pixels, *width, *height, surface->pitch, *image, alpha ); + *format = mlt_image_rgb24a; + image_size = *width * *height * 4; + *image = mlt_pool_alloc( image_size ); + memcpy( *image, surface->pixels, image_size ); break; case 24: - mlt_convert_rgb24_to_yuv422( surface->pixels, *width, *height, surface->pitch, *image ); - memset( alpha, 255, *width * *height ); + *format = mlt_image_rgb24; + *image = mlt_pool_alloc( image_size ); + memcpy( *image, surface->pixels, image_size ); break; default: - mlt_convert_rgb24_to_yuv422( converted->pixels, *width, *height, converted->pitch, *image ); - memset( alpha, 255, *width * *height ); + *image = mlt_pool_alloc( image_size ); + memcpy( *image, converted->pixels, image_size ); break; } @@ -79,8 +80,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **image, mlt_image_forma SDL_FreeSurface( converted ); // Update the frame - mlt_properties_set_data( properties, "image", *image, *width * *height * 2, mlt_pool_release, NULL ); - mlt_properties_set_data( properties, "alpha", alpha, *width * *height, mlt_pool_release, NULL ); + mlt_properties_set_data( properties, "image", *image, image_size, mlt_pool_release, NULL ); mlt_properties_set_int( properties, "width", *width ); mlt_properties_set_int( properties, "height", *height ); diff --git a/src/modules/vmfx/filter_chroma.c b/src/modules/vmfx/filter_chroma.c index de54135c..df8c4bfb 100644 --- a/src/modules/vmfx/filter_chroma.c +++ b/src/modules/vmfx/filter_chroma.c @@ -53,6 +53,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format RGB2YUV( r, g, b, y, u, v ); + *format = mlt_image_yuv422; if ( mlt_frame_get_image( frame, image, format, width, height, writable ) == 0 ) { uint8_t *alpha = mlt_frame_get_alpha_mask( frame ); diff --git a/src/modules/vmfx/filter_chroma_hold.c b/src/modules/vmfx/filter_chroma_hold.c index 07ca4a80..d375faa5 100644 --- a/src/modules/vmfx/filter_chroma_hold.c +++ b/src/modules/vmfx/filter_chroma_hold.c @@ -53,6 +53,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format RGB2YUV( r, g, b, y, u, v ); + *format = mlt_image_yuv422; if ( mlt_frame_get_image( frame, image, format, width, height, writable ) == 0 ) { uint8_t alpha = 0; diff --git a/src/modules/vmfx/filter_mono.c b/src/modules/vmfx/filter_mono.c index f7ea11d0..7e75f940 100644 --- a/src/modules/vmfx/filter_mono.c +++ b/src/modules/vmfx/filter_mono.c @@ -35,6 +35,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * int invert = mlt_deque_pop_back_int( MLT_FRAME_IMAGE_STACK( this ) ); // Render the frame + *format = mlt_image_yuv422; if ( mlt_frame_get_image( this, image, format, width, height, writable ) == 0 ) { uint8_t *p = *image; diff --git a/src/modules/vmfx/filter_shape.c b/src/modules/vmfx/filter_shape.c index fdd33e43..00b0ed08 100644 --- a/src/modules/vmfx/filter_shape.c +++ b/src/modules/vmfx/filter_shape.c @@ -49,6 +49,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * int invert = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "invert" ) * 255; // Render the frame + *format = mlt_image_yuv422; if ( mlt_frame_get_image( this, image, format, width, height, writable ) == 0 && ( !use_luminance || ( int )mix != 1 ) ) { // Get the alpha mask of the source diff --git a/src/modules/xine/filter_deinterlace.c b/src/modules/xine/filter_deinterlace.c index 01871cf3..840b5f07 100644 --- a/src/modules/xine/filter_deinterlace.c +++ b/src/modules/xine/filter_deinterlace.c @@ -19,6 +19,7 @@ */ #include +#include #include "deinterlace.h" #include @@ -33,19 +34,25 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * { int error = 0; int deinterlace = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "consumer_deinterlace" ); + int progressive = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ); // Pop the service off the stack mlt_filter filter = mlt_frame_pop_service( this ); // Determine if we need a writable version or not if ( deinterlace && !writable ) - writable = !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ); + writable = !progressive; // Get the input image + if ( deinterlace && !progressive ) + *format = mlt_image_yuv422; + mlt_log_debug( MLT_FILTER_SERVICE( filter ), "xine.deinterlace %d prog %d format %s\n", + deinterlace, progressive, mlt_image_format_name( *format ) ); error = mlt_frame_get_image( this, image, format, width, height, writable ); + progressive = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ); // Check that we want progressive and we aren't already progressive - if ( deinterlace && *format == mlt_image_yuv422 && *image != NULL && !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ) ) + if ( deinterlace && *format == mlt_image_yuv422 && *image && !progressive ) { // Determine deinterlace method char *method_str = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "method" ); -- 2.39.2