X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Favformat%2Ffilter_avcolour_space.c;h=9ea2b8fee8e1894e9dbaba57666afd11072ceea7;hb=85847996a23da6ee205cf35a4d8230c1cc66c6a5;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..9ea2b8f 100644 --- a/src/modules/avformat/filter_avcolour_space.c +++ b/src/modules/avformat/filter_avcolour_space.c @@ -28,6 +28,14 @@ #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 +54,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 +65,11 @@ 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( &output, out, out_fmt, width, height ); + avpicture_fill( &input, in, in_fmt, width, height ); + img_convert( &output, out_fmt, &input, in_fmt, width, height ); } /** Do it :-). @@ -125,18 +88,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; }