#!/bin/sh
-export version=0.4.4
-export soversion=1
+export version=0.4.5
+export soversion=2
show_help()
{
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
#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"
#include "mlt_producer.h"
#include "mlt_factory.h"
#include "mlt_profile.h"
+#include "mlt_log.h"
#include <stdio.h>
#include <stdlib.h>
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.
*/
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
{
/***** 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;
/* 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;
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)\
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 );
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
// ffmpeg Header files
#include <avformat.h>
#endif
#if LIBAVUTIL_VERSION_INT < (50<<16)
-#define PIX_FMT_RGB32 PIX_FMT_RGBA32
#define PIX_FMT_YUYV422 PIX_FMT_YUV422
#endif
value = PIX_FMT_RGB24;
break;
case mlt_image_rgb24a:
- value = PIX_FMT_RGB32;
+ case mlt_image_opengl:
+ value = PIX_FMT_RGBA;
break;
case mlt_image_yuv422:
value = PIX_FMT_YUYV422;
case mlt_image_yuv420p:
value = PIX_FMT_YUV420P;
break;
- case mlt_image_opengl:
case mlt_image_none:
- 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;
/** 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 );
p += 4;
}
o -= ostride;
- alpha -= *width;
+ alpha -= width;
}
mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL );
*format = output_format;
}
}
-
return error;
}
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;
}
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" ) )
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 );
#define PIX_FMT_YUYV422 PIX_FMT_YUV422
#endif
-static inline int is_big_endian( )
-{
- union { int i; char c[ 4 ]; } big_endian_test;
- big_endian_test.i = 1;
-
- return big_endian_test.c[ 0 ] != 1;
-}
-
static inline int convert_mlt_to_av_cs( mlt_image_format format )
{
int value = 0;
value = PIX_FMT_RGB24;
break;
case mlt_image_rgb24a:
+ case mlt_image_opengl:
value = PIX_FMT_RGB32;
break;
case mlt_image_yuv422:
case mlt_image_yuv420p:
value = PIX_FMT_YUV420P;
break;
- case mlt_image_opengl:
case mlt_image_none:
fprintf( stderr, "Invalid format...\n" );
break;
return value;
}
-static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iformat, mlt_image_format oformat, int iwidth, int iheight, int owidth, int oheight )
+static int filter_scale( mlt_frame 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 );
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
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 );
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);
#include <pthread.h>
#if LIBAVUTIL_VERSION_INT < (50<<16)
+#define PIX_FMT_RGB32 PIX_FMT_RGBA32
#define PIX_FMT_YUYV422 PIX_FMT_YUV422
#endif
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,
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;
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;
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 );
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 );
filter_data_show.o \
filter_gamma.o \
filter_greyscale.o \
+ filter_imageconvert.o \
filter_luma.o \
filter_mirror.o \
filter_mono.o \
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 );
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 );
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" );
*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" ) )
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" );
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;
--- /dev/null
+/*
+ * filter_imageconvert.c -- colorspace and pixel format converter
+ * Copyright (C) 2009 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * 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 <framework/mlt_filter.h>
+#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
+#include <framework/mlt_pool.h>
+
+#include <stdlib.h>
+
+
+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;
+}
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 )
{
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;
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 )
{
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
-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;
}
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 )
}
// 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 );
// 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
{
*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 :-).
*/
// 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" ) )
// 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 );
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
{
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
# 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
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 );
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, '/' ) )
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;
}
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
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
{
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" );
}
}
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" ) );
*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.
*/
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 );
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" );
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)
}
i += 2;
}
-
- mlt_convert_rgb24a_to_yuv422((uint8_t *)dest, *width, *height, *width * sizeof(RGB32),
- *image, NULL );
-
- mlt_pool_release(dest);
}
return error;
{
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 );
}
return frame;
}
-void filter_close( mlt_filter this ){
-
+void filter_close( mlt_filter this )
+{
destruct( MLT_FILTER_PROPERTIES ( this ) );
-
}
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);
}
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;
}
*/
#include <framework/mlt.h>
-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 );
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 );
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;
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 );
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 );
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" );
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
-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 );
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 );
// 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;
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;
char *markup;
char *text;
char *font;
- int weight;
+ int weight;
};
// special color type used by internal pango routines
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
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 ) )
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 );
}
// 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
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" );
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 );
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;
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
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 );
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;
};
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" ) )
{
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;
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 );
{
pthread_mutex_unlock( &this->mutex );
mlt_cache_item_close( this->image_cache );
- mlt_cache_item_close( this->alpha_cache );
}
// Set width/height of frame
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 );
}
// 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
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 );
}
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) {
DoBoxBlur (*image, rgb, *width, h, (int) factor*hori, (int) factor*vert);
mlt_pool_release (rgb);
}
- }
+ }
return error;
}
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;
}
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;
}
// 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 );
// 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;
// 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
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 );
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 )
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 )
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 );
}
if (piccount>0 )
return 0;
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
+ if ( error == 0 && *image )
{
int h = *height;
{
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;
{
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;
{
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;
{
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;
{
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 );
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 );
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" );
// 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;
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;
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
// 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
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 );
}
#include <QtGui/QImage>
#include <QtCore/QSysInfo>
#include <QtCore/QMutex>
+#include <QtCore/QtEndian>
#endif
self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" );
self->current_image = static_cast<uint8_t*>( 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<uint8_t*>( 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" ) )
{
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;
#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;
}
{
pthread_mutex_unlock( &self->mutex );
mlt_cache_item_close( self->image_cache );
- mlt_cache_item_close( self->alpha_cache );
}
// Set width/height of frame
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();
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;
};
SDL_Rect rect;
uint8_t *buffer;
int bpp;
- int filtered;
};
/** Forward references to static functions.
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 )
#include <framework/mlt_deque.h>
#include <framework/mlt_factory.h>
#include <framework/mlt_filter.h>
+#include <framework/mlt_log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
uint8_t *buffer;
int last_position;
mlt_producer last_producer;
- int filtered;
};
/** Forward references to static functions.
// 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;
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;
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 );
// 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 )
}
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 );
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 )
{
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;
}
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 );
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 );
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;
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;
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
*/
#include <framework/mlt_filter.h>
+#include <framework/mlt_log.h>
#include "deinterlace.h"
#include <framework/mlt_frame.h>
{
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" );