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 converts a YUV value to the RGB color space. */
41 #define YUV2RGB_601_UNSCALED( y, u, v, r, g, b ) \
42 r = ((1024 * y + 1404 * ( v - 128 ) ) >> 10 ); \
43 g = ((1024 * y - 715 * ( v - 128 ) - 345 * ( u - 128 ) ) >> 10 ); \
44 b = ((1024 * y + 1774 * ( 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;
51 #define RGB2YUV_601 RGB2YUV_601_SCALED
52 #define YUV2RGB_601 YUV2RGB_601_SCALED
54 #define RGB2YUV_601 RGB2YUV_601_UNSCALED
55 #define YUV2RGB_601 YUV2RGB_601_UNSCALED
58 static int convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, uint8_t *alpha, int width, int height )
63 int total = width * height / 2 + 1;
70 YUV2RGB_601( yy, uu, vv, r, g, b );
76 YUV2RGB_601( yy, uu, vv, r, g, b );
87 static int convert_yuv422_to_rgb24( uint8_t *yuv, uint8_t *rgb, uint8_t *alpha, int width, int height )
92 int total = width * height / 2 + 1;
99 YUV2RGB_601( yy, uu, vv, r, g, b );
104 YUV2RGB_601( yy, uu, vv, r, g, b );
114 static int convert_rgb24a_to_yuv422( uint8_t *rgba, uint8_t *yuv, uint8_t *alpha, int width, int height )
117 int stride = width * 4;
118 int y0, y1, u0, u1, v0, v1;
120 uint8_t *s, *d = yuv;
121 int i, j, n = width / 2 + 1;
124 for ( i = 0; i < height; i++ )
126 s = rgba + ( stride * i );
134 RGB2YUV_601( r, g, b, y0, u0 , v0 );
139 RGB2YUV_601( r, g, b, y1, u1 , v1 );
151 RGB2YUV_601( r, g, b, y0, u0 , v0 );
157 for ( i = 0; i < height; i++ )
159 s = rgba + ( stride * i );
167 RGB2YUV_601( r, g, b, y0, u0 , v0 );
172 RGB2YUV_601( r, g, b, y1, u1 , v1 );
184 RGB2YUV_601( r, g, b, y0, u0 , v0 );
193 static int convert_rgb24_to_yuv422( uint8_t *rgb, uint8_t *yuv, uint8_t *alpha, int width, int height )
196 int stride = width * 3;
197 int y0, y1, u0, u1, v0, v1;
199 uint8_t *s, *d = yuv;
200 int i, j, n = width / 2 + 1;
202 for ( i = 0; i < height; i++ )
204 s = rgb + ( stride * i );
211 RGB2YUV_601( r, g, b, y0, u0 , v0 );
215 RGB2YUV_601( r, g, b, y1, u1 , v1 );
226 RGB2YUV_601( r, g, b, y0, u0 , v0 );
234 static int convert_yuv420p_to_yuv422( uint8_t *yuv420p, uint8_t *yuv, uint8_t *alpha, int width, int height )
238 int half = width >> 1;
239 uint8_t *Y = yuv420p;
240 uint8_t *U = Y + width * height;
241 uint8_t *V = U + width * height / 4;
244 for ( i = 0; i < height; i++ )
246 uint8_t *u = U + ( i / 2 ) * ( half );
247 uint8_t *v = V + ( i / 2 ) * ( half );
261 static int convert_rgb24_to_rgb24a( uint8_t *rgb, uint8_t *rgba, uint8_t *alpha, int width, int height )
265 int total = width * height + 1;
278 static int convert_rgb24a_to_rgb24( uint8_t *rgba, uint8_t *rgb, uint8_t *alpha, int width, int height )
282 int total = width * height + 1;
295 typedef int ( *conversion_function )( uint8_t *yuv, uint8_t *rgba, uint8_t *alpha, int width, int height );
297 static conversion_function conversion_matrix[5][5] = {
298 { NULL, convert_rgb24_to_rgb24a, convert_rgb24_to_yuv422, NULL, convert_rgb24_to_rgb24a },
299 { convert_rgb24a_to_rgb24, NULL, convert_rgb24a_to_yuv422, NULL, NULL },
300 { convert_yuv422_to_rgb24, convert_yuv422_to_rgb24a, NULL, NULL, convert_yuv422_to_rgb24a },
301 { NULL, NULL, convert_yuv420p_to_yuv422, NULL, NULL },
302 { convert_rgb24a_to_rgb24, NULL, convert_rgb24a_to_yuv422, NULL, NULL },
305 static uint8_t bpp_table[4] = { 3, 4, 2, 0 };
307 static int convert_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, mlt_image_format requested_format )
310 mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
311 int width = mlt_properties_get_int( properties, "width" );
312 int height = mlt_properties_get_int( properties, "height" );
314 if ( *format != requested_format )
316 conversion_function converter = conversion_matrix[ *format - 1 ][ requested_format - 1 ];
318 mlt_log_debug( NULL, "[filter imageconvert] %s -> %s @ %dx%d\n",
319 mlt_image_format_name( *format ), mlt_image_format_name( requested_format ),
323 int size = width * height * bpp_table[ requested_format - 1 ];
324 int alpha_size = width * height;
325 uint8_t *image = mlt_pool_alloc( size );
326 uint8_t *alpha = ( *format == mlt_image_rgb24a ||
327 *format == mlt_image_opengl )
328 ? mlt_pool_alloc( width * height ) : NULL;
329 if ( requested_format == mlt_image_rgb24a || requested_format == mlt_image_opengl )
332 mlt_pool_release( alpha );
333 alpha = mlt_frame_get_alpha_mask( frame );
334 mlt_properties_get_data( properties, "alpha", &alpha_size );
337 if ( !( error = converter( *buffer, image, alpha, width, height ) ) )
339 mlt_frame_set_image( frame, image, size, mlt_pool_release );
340 if ( alpha && ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) )
341 mlt_frame_set_alpha( frame, alpha, alpha_size, mlt_pool_release );
343 *format = requested_format;
347 mlt_pool_release( image );
349 mlt_pool_release( alpha );
361 /** Filter processing.
364 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
366 if ( !frame->convert_image )
367 frame->convert_image = convert_image;
371 /** Constructor for the filter.
374 mlt_filter filter_imageconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
376 mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
377 if ( mlt_filter_init( this, this ) == 0 )
379 this->process = filter_process;