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>
29 static int convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total )
40 YUV2RGB(yy, uu, vv, r, g, b);
46 YUV2RGB(yy, uu, vv, r, g, b);
57 static int convert_yuv422_to_rgb24( uint8_t *yuv, uint8_t *rgb, unsigned int total )
68 YUV2RGB(yy, uu, vv, r, g, b);
73 YUV2RGB(yy, uu, vv, r, g, b);
83 static int convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
86 register int y0, y1, u0, u1, v0, v1;
88 register uint8_t *d = yuv;
92 for ( i = 0; i < height; i++ )
94 register uint8_t *s = rgba + ( stride * i );
95 for ( j = 0; j < ( width / 2 ); j++ )
101 RGB2YUV (r, g, b, y0, u0 , v0);
106 RGB2YUV (r, g, b, y1, u1 , v1);
118 RGB2YUV (r, g, b, y0, u0 , v0);
124 for ( i = 0; i < height; i++ )
126 register uint8_t *s = rgba + ( stride * i );
127 for ( j = 0; j < ( width / 2 ); j++ )
133 RGB2YUV (r, g, b, y0, u0 , v0);
138 RGB2YUV (r, g, b, y1, u1 , v1);
150 RGB2YUV (r, g, b, y0, u0 , v0);
159 static int convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
162 register int y0, y1, u0, u1, v0, v1;
163 register int r, g, b;
164 register uint8_t *d = yuv;
167 for ( i = 0; i < height; i++ )
169 register uint8_t *s = rgb + ( stride * i );
170 for ( j = 0; j < ( width / 2 ); j++ )
175 RGB2YUV (r, g, b, y0, u0 , v0);
179 RGB2YUV (r, g, b, y1, u1 , v1);
190 RGB2YUV (r, g, b, y0, u0 , v0);
198 static int convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, uint8_t *yuv )
203 int half = width >> 1;
205 uint8_t *Y = yuv420p;
206 uint8_t *U = Y + width * height;
207 uint8_t *V = U + width * height / 4;
209 register uint8_t *d = yuv;
211 for ( i = 0; i < height; i++ )
213 register uint8_t *u = U + ( i / 2 ) * ( half );
214 register uint8_t *v = V + ( i / 2 ) * ( half );
216 for ( j = 0; j < half; j++ )
227 static int convert_rgb24_to_rgb24a( uint8_t *rgb, uint8_t *rgba, int total )
242 static int convert_rgb24a_to_rgb24( uint8_t *rgba, uint8_t *rgb, int total, uint8_t *alpha )
257 static int convert_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, mlt_image_format requested_format )
260 mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
261 int width = mlt_properties_get_int( properties, "width" );
262 int height = mlt_properties_get_int( properties, "height" );
264 if ( *format != requested_format )
266 mlt_log_debug( NULL, "[filter imageconvert] %s -> %s\n",
267 mlt_image_format_name( *format ), mlt_image_format_name( requested_format ) );
270 case mlt_image_yuv422:
271 switch ( requested_format )
273 case mlt_image_rgb24:
275 uint8_t *rgb = mlt_pool_alloc( width * height * 3 );
276 error = convert_yuv422_to_rgb24( *buffer, rgb, width * height );
279 mlt_pool_release( rgb );
283 mlt_properties_set_data( properties, "image", rgb, width * height * 3, mlt_pool_release, NULL );
285 *format = mlt_image_rgb24;
289 case mlt_image_rgb24a:
290 case mlt_image_opengl:
292 uint8_t *rgba = mlt_pool_alloc( width * height * 4 );
293 error = convert_yuv422_to_rgb24a( *buffer, rgba, width * height );
296 mlt_pool_release( rgba );
300 mlt_properties_set_data( properties, "image", rgba, width * height * 4, mlt_pool_release, NULL );
302 *format = requested_format;
310 case mlt_image_rgb24:
311 switch ( requested_format )
313 case mlt_image_yuv422:
315 uint8_t *yuv = mlt_pool_alloc( width * height * 2 );
316 error = convert_rgb24_to_yuv422( *buffer, width, height, width * 3, yuv );
319 mlt_pool_release( yuv );
323 mlt_properties_set_data( properties, "image", yuv, width * height * 2, mlt_pool_release, NULL );
325 *format = mlt_image_yuv422;
329 case mlt_image_rgb24a:
330 case mlt_image_opengl:
332 uint8_t *rgba = mlt_pool_alloc( width * height * 4 );
333 error = convert_rgb24_to_rgb24a( *buffer, rgba, width * height );
336 mlt_pool_release( rgba );
340 mlt_properties_set_data( properties, "image", rgba, width * height * 4, mlt_pool_release, NULL );
342 *format = requested_format;
350 case mlt_image_rgb24a:
351 case mlt_image_opengl:
352 switch ( requested_format )
354 case mlt_image_yuv422:
356 uint8_t *yuv = mlt_pool_alloc( width * height * 2 );
357 uint8_t *alpha = mlt_pool_alloc( width * height );
358 error = convert_rgb24a_to_yuv422( *buffer, width, height, width * 4, yuv, alpha );
361 mlt_pool_release( yuv );
362 mlt_pool_release( alpha );
366 mlt_properties_set_data( properties, "image", yuv, width * height * 2, mlt_pool_release, NULL );
367 mlt_properties_set_data( properties, "alpha", alpha, width * height, mlt_pool_release, NULL );
369 *format = mlt_image_yuv422;
373 case mlt_image_rgb24:
375 uint8_t *rgb = mlt_pool_alloc( width * height * 3 );
376 uint8_t *alpha = mlt_pool_alloc( width * height );
377 error = convert_rgb24a_to_rgb24( *buffer, rgb, width * height, alpha );
380 mlt_pool_release( rgb );
381 mlt_pool_release( alpha );
385 mlt_properties_set_data( properties, "image", rgb, width * height * 3, mlt_pool_release, NULL );
386 mlt_properties_set_data( properties, "alpha", alpha, width * height, mlt_pool_release, NULL );
388 *format = mlt_image_rgb24;
392 case mlt_image_rgb24a:
393 case mlt_image_opengl:
394 *format = requested_format;
400 case mlt_image_yuv420p:
401 switch ( requested_format )
403 case mlt_image_rgb24:
404 case mlt_image_rgb24a:
405 case mlt_image_opengl:
406 case mlt_image_yuv422:
408 uint8_t *yuv = mlt_pool_alloc( width * height * 2 );
409 int error = convert_yuv420p_to_yuv422( *buffer, width, height, yuv );
412 mlt_pool_release( yuv );
416 mlt_properties_set_data( properties, "image", yuv, width * height * 2, mlt_pool_release, NULL );
418 *format = mlt_image_yuv422;
420 switch ( requested_format )
422 case mlt_image_yuv422:
424 case mlt_image_rgb24:
425 case mlt_image_rgb24a:
426 case mlt_image_opengl:
427 error = convert_image( frame, buffer, format, requested_format );
444 mlt_properties_set_int( properties, "format", *format );
449 /** Filter processing.
452 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
454 frame->convert_image = convert_image;
458 /** Constructor for the filter.
461 mlt_filter filter_imageconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
463 mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
464 if ( mlt_filter_init( this, this ) == 0 )
466 this->process = filter_process;