2 * filter_imageconvert.c -- colorspace and pixel format converter
3 * Copyright (C) 2009 Ushodaya Enterprises Limited
4 * Author: Dan Dennedy <dan@dennedy.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <framework/mlt_filter.h>
22 #include <framework/mlt_frame.h>
23 #include <framework/mlt_log.h>
24 #include <framework/mlt_pool.h>
28 /** This macro converts a YUV value to the RGB color space. */
29 #define RGB2YUV_601_UNSCALED(r, g, b, y, u, v)\
30 y = (299*r + 587*g + 114*b) >> 10;\
31 u = ((-169*r - 331*g + 500*b) >> 10) + 128;\
32 v = ((500*r - 419*g - 81*b) >> 10) + 128;\
36 y = y > 235 ? 235 : y;\
37 u = u > 240 ? 240 : u;\
40 /** This macro scales YUV up into the full gamut of the RGB color space. */
41 #define YUV2RGB_601_SCALED( y, u, v, r, g, b ) \
42 r = ((1192 * ( y - 16 ) + 1634 * ( v - 128 ) ) >> 10 ); \
43 g = ((1192 * ( y - 16 ) - 832 * ( v - 128 ) - 401 * ( u - 128 ) ) >> 10 ); \
44 b = ((1192 * ( y - 16 ) + 2066 * ( u - 128 ) ) >> 10 ); \
45 r = r < 0 ? 0 : r > 255 ? 255 : r; \
46 g = g < 0 ? 0 : g > 255 ? 255 : g; \
47 b = b < 0 ? 0 : b > 255 ? 255 : b;
49 /** This macro converts a YUV value to the RGB color space. */
50 #define YUV2RGB_601_UNSCALED( y, u, v, r, g, b ) \
51 r = ((1024 * y + 1404 * ( v - 128 ) ) >> 10 ); \
52 g = ((1024 * y - 715 * ( v - 128 ) - 345 * ( u - 128 ) ) >> 10 ); \
53 b = ((1024 * y + 1774 * ( u - 128 ) ) >> 10 ); \
54 r = r < 0 ? 0 : r > 255 ? 255 : r; \
55 g = g < 0 ? 0 : g > 255 ? 255 : g; \
56 b = b < 0 ? 0 : b > 255 ? 255 : b;
60 #define RGB2YUV_601 RGB2YUV_601_SCALED
61 #define YUV2RGB_601 YUV2RGB_601_SCALED
63 #define RGB2YUV_601 RGB2YUV_601_UNSCALED
64 #define YUV2RGB_601 YUV2RGB_601_UNSCALED
67 static int convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, uint8_t *alpha, int width, int height )
72 int total = width * height / 2 + 1;
79 YUV2RGB_601( yy, uu, vv, r, g, b );
85 YUV2RGB_601( yy, uu, vv, r, g, b );
96 static int convert_yuv422_to_rgb24( uint8_t *yuv, uint8_t *rgb, uint8_t *alpha, int width, int height )
101 int total = width * height / 2 + 1;
108 YUV2RGB_601( yy, uu, vv, r, g, b );
113 YUV2RGB_601( yy, uu, vv, r, g, b );
123 static int convert_rgb24a_to_yuv422( uint8_t *rgba, uint8_t *yuv, uint8_t *alpha, int width, int height )
126 int stride = width * 4;
127 int y0, y1, u0, u1, v0, v1;
129 uint8_t *s, *d = yuv;
130 int i, j, n = width / 2 + 1;
133 for ( i = 0; i < height; i++ )
135 s = rgba + ( stride * i );
143 RGB2YUV_601( r, g, b, y0, u0 , v0 );
148 RGB2YUV_601( r, g, b, y1, u1 , v1 );
160 RGB2YUV_601( r, g, b, y0, u0 , v0 );
166 for ( i = 0; i < height; i++ )
168 s = rgba + ( stride * i );
176 RGB2YUV_601( r, g, b, y0, u0 , v0 );
181 RGB2YUV_601( r, g, b, y1, u1 , v1 );
193 RGB2YUV_601( r, g, b, y0, u0 , v0 );
202 static int convert_rgb24_to_yuv422( uint8_t *rgb, uint8_t *yuv, uint8_t *alpha, int width, int height )
205 int stride = width * 3;
206 int y0, y1, u0, u1, v0, v1;
208 uint8_t *s, *d = yuv;
209 int i, j, n = width / 2 + 1;
211 for ( i = 0; i < height; i++ )
213 s = rgb + ( stride * i );
220 RGB2YUV_601( r, g, b, y0, u0 , v0 );
224 RGB2YUV_601( r, g, b, y1, u1 , v1 );
235 RGB2YUV_601( r, g, b, y0, u0 , v0 );
243 static int convert_yuv420p_to_yuv422( uint8_t *yuv420p, uint8_t *yuv, uint8_t *alpha, int width, int height )
247 int half = width >> 1;
248 uint8_t *Y = yuv420p;
249 uint8_t *U = Y + width * height;
250 uint8_t *V = U + width * height / 4;
253 for ( i = 0; i < height; i++ )
255 uint8_t *u = U + ( i / 2 ) * ( half );
256 uint8_t *v = V + ( i / 2 ) * ( half );
270 static int convert_rgb24_to_rgb24a( uint8_t *rgb, uint8_t *rgba, uint8_t *alpha, int width, int height )
274 int total = width * height + 1;
287 static int convert_rgb24a_to_rgb24( uint8_t *rgba, uint8_t *rgb, uint8_t *alpha, int width, int height )
291 int total = width * height + 1;
304 typedef int ( *conversion_function )( uint8_t *yuv, uint8_t *rgba, uint8_t *alpha, int width, int height );
306 static conversion_function conversion_matrix[5][5] = {
307 { NULL, convert_rgb24_to_rgb24a, convert_rgb24_to_yuv422, NULL, convert_rgb24_to_rgb24a },
308 { convert_rgb24a_to_rgb24, NULL, convert_rgb24a_to_yuv422, NULL, NULL },
309 { convert_yuv422_to_rgb24, convert_yuv422_to_rgb24a, NULL, NULL, convert_yuv422_to_rgb24a },
310 { NULL, NULL, convert_yuv420p_to_yuv422, NULL, NULL },
311 { convert_rgb24a_to_rgb24, NULL, convert_rgb24a_to_yuv422, NULL, NULL },
314 static uint8_t bpp_table[4] = { 3, 4, 2, 0 };
316 static int convert_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, mlt_image_format requested_format )
319 mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
320 int width = mlt_properties_get_int( properties, "width" );
321 int height = mlt_properties_get_int( properties, "height" );
323 if ( *format != requested_format )
325 conversion_function converter = conversion_matrix[ *format - 1 ][ requested_format - 1 ];
327 mlt_log_debug( NULL, "[filter imageconvert] %s -> %s @ %dx%d\n",
328 mlt_image_format_name( *format ), mlt_image_format_name( requested_format ),
332 int size = width * height * bpp_table[ requested_format - 1 ];
333 int alpha_size = width * height;
334 uint8_t *image = mlt_pool_alloc( size );
335 uint8_t *alpha = ( *format == mlt_image_rgb24a ||
336 *format == mlt_image_opengl )
337 ? mlt_pool_alloc( width * height ) : NULL;
338 if ( requested_format == mlt_image_rgb24a || requested_format == mlt_image_opengl )
341 mlt_pool_release( alpha );
342 alpha = mlt_frame_get_alpha_mask( frame );
343 mlt_properties_get_data( properties, "alpha", &alpha_size );
346 if ( !( error = converter( *buffer, image, alpha, width, height ) ) )
348 mlt_frame_set_image( frame, image, size, mlt_pool_release );
349 if ( alpha && ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) )
350 mlt_frame_set_alpha( frame, alpha, alpha_size, mlt_pool_release );
352 *format = requested_format;
356 mlt_pool_release( image );
358 mlt_pool_release( alpha );
370 /** Filter processing.
373 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
375 if ( !frame->convert_image )
376 frame->convert_image = convert_image;
380 /** Constructor for the filter.
383 mlt_filter filter_imageconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
385 mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
386 if ( mlt_filter_init( this, this ) == 0 )
388 this->process = filter_process;