X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Favformat%2Ffilter_avcolour_space.c;h=9c9747277516029dfb1aa8bff62ed8240c304e12;hb=bf3264b9e340ba5c11cbf59835a8af3db94e0cc2;hp=3853a18d3b332a496e3d7e673c7d851122d3b791;hpb=0e74ed81ec64c74087d3576b55ad7c09ce08e1bb;p=melted diff --git a/src/modules/avformat/filter_avcolour_space.c b/src/modules/avformat/filter_avcolour_space.c index 3853a18..9c97472 100644 --- a/src/modules/avformat/filter_avcolour_space.c +++ b/src/modules/avformat/filter_avcolour_space.c @@ -3,19 +3,19 @@ * Copyright (C) 2004-2005 Ushodaya Enterprises Limited * Author: Charles Yates * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * 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 program is distributed in the hope that it will be useful, + * 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 General Public License for more details. + * 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 General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * 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 "filter_avcolour_space.h" @@ -24,10 +24,21 @@ // ffmpeg Header files #include +#ifdef SWSCALE +#include +#endif #include #include +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; @@ -46,6 +57,7 @@ static inline int convert_mlt_to_av_cs( mlt_image_format format ) case mlt_image_yuv420p: value = PIX_FMT_YUV420P; break; + case mlt_image_opengl: case mlt_image_none: fprintf( stderr, "Invalid format...\n" ); break; @@ -56,57 +68,19 @@ static inline int convert_mlt_to_av_cs( mlt_image_format format ) static inline void convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, int width, int height ) { - if ( in_fmt == PIX_FMT_YUV420P && out_fmt == PIX_FMT_YUV422 ) - { - register int i, j; - register int half = width >> 1; - register uint8_t *Y = in; - register uint8_t *U = Y + width * height; - register uint8_t *V = U + width * height / 2; - register uint8_t *d = out; - register uint8_t *y, *u, *v; - - i = height >> 1; - while ( i -- ) - { - y = Y; - u = U; - v = V; - j = half; - while ( j -- ) - { - *d ++ = *y ++; - *d ++ = *u ++; - *d ++ = *y ++; - *d ++ = *v ++; - } - - Y += width; - y = Y; - u = U; - v = V; - j = half; - while ( j -- ) - { - *d ++ = *y ++; - *d ++ = *u ++; - *d ++ = *y ++; - *d ++ = *v ++; - } - - Y += width; - U += width / 2; - V += width / 2; - } - } - else - { - AVPicture input; - AVPicture output; - avpicture_fill( &output, out, out_fmt, width, height ); - avpicture_fill( &input, in, in_fmt, width, height ); - img_convert( &output, out_fmt, &input, in_fmt, width, height ); - } + AVPicture input; + AVPicture output; + avpicture_fill( &input, in, in_fmt, width, height ); + avpicture_fill( &output, out, out_fmt, width, height ); +#ifdef SWSCALE + struct SwsContext *context = sws_getContext( width, height, in_fmt, + width, height, out_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL); + sws_scale( context, input.data, input.linesize, 0, height, + output.data, output.linesize); + sws_freeContext( context ); +#else + img_convert( &output, out_fmt, &input, in_fmt, width, height ); +#endif } /** Do it :-). @@ -125,18 +99,124 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format * error = mlt_frame_get_image( this, image, format, width, height, 0 ); - if ( error == 0 && *format != output_format && *width > 0 && *height > 0 ) + if ( error == 0 && *format != output_format && *image != NULL && output_format != mlt_image_opengl ) { 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 ) + { + 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 ) + { + 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 ) + { + int size = *width * *height * 4; + uint8_t *output = mlt_pool_alloc( size ); + 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; + int r, g, b; + + while( h -- ) + { + w = *width; + o -= ostride; + alpha -= *width; + while( w >= 2 ) + { + YUV2RGB( *p, *( p + 1 ), *( p + 3 ), r, g, b ); + *o ++ = r; + *o ++ = g; + *o ++ = b; + *o ++ = *alpha ++; + YUV2RGB( *( p + 2 ), *( p + 1 ), *( p + 3 ), r, g, b ); + *o ++ = r; + *o ++ = g; + *o ++ = b; + *o ++ = *alpha ++; + w -= 2; + p += 4; + } + o -= ostride; + alpha -= *width; + } + + mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL ); + mlt_properties_set_int( properties, "format", output_format ); + *image = output; + *format = output_format; + } + } + return error; }