X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_chroma%2Fi420_rgb.c;h=1427a99e338a25a3b0e43a55bac0cca3bcb7d5ab;hb=456aa837c26aab85cdd46553d26ca3623e79e2fc;hp=e2475e9d6b55be0693b9b3612c450ea3d80944c8;hpb=19ea8feb6db01c1deafb19f35ecee8eff81aeb02;p=vlc diff --git a/modules/video_chroma/i420_rgb.c b/modules/video_chroma/i420_rgb.c index e2475e9d6b..1427a99e33 100644 --- a/modules/video_chroma/i420_rgb.c +++ b/modules/video_chroma/i420_rgb.c @@ -1,16 +1,17 @@ /***************************************************************************** * i420_rgb.c : YUV to bitmap RGB conversion module for vlc ***************************************************************************** - * Copyright (C) 2000, 2001 VideoLAN - * $Id: i420_rgb.c,v 1.1 2002/08/04 17:23:43 sam Exp $ + * Copyright (C) 2000, 2001, 2004 the VideoLAN team + * $Id$ * - * Authors: Samuel Hocevar + * Authors: Sam Hocevar + * Damien Fouilleul * * 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 program 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 @@ -18,25 +19,38 @@ * * 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, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ #include /* exp(), pow() */ -#include /* ENOMEM */ -#include /* strerror() */ -#include /* malloc(), free() */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include -#include +#include +#include #include "i420_rgb.h" #if defined (MODULE_NAME_IS_i420_rgb) # include "i420_rgb_c.h" #endif +/***************************************************************************** + * RGB2PIXEL: assemble RGB components to a pixel value, returns a uint32_t + *****************************************************************************/ +#define RGB2PIXEL( p_vout, i_r, i_g, i_b ) \ + (((((uint32_t)i_r) >> p_vout->output.i_rrshift) \ + << p_vout->output.i_lrshift) \ + | ((((uint32_t)i_g) >> p_vout->output.i_rgshift) \ + << p_vout->output.i_lgshift) \ + | ((((uint32_t)i_b) >> p_vout->output.i_rbshift) \ + << p_vout->output.i_lbshift)) + /***************************************************************************** * Local and extern prototypes. *****************************************************************************/ @@ -46,7 +60,7 @@ static void Deactivate ( vlc_object_t * ); #if defined (MODULE_NAME_IS_i420_rgb) static void SetGammaTable ( int *pi_table, double f_gamma ); static void SetYUV ( vout_thread_t * ); -static void Set8bppPalette ( vout_thread_t *, u8 * ); +static void Set8bppPalette ( vout_thread_t *, uint8_t * ); #endif /***************************************************************************** @@ -54,14 +68,19 @@ static void Set8bppPalette ( vout_thread_t *, u8 * ); *****************************************************************************/ vlc_module_begin(); #if defined (MODULE_NAME_IS_i420_rgb) - set_description( _("I420,IYUV,YV12 to " - "RGB,RV15,RV16,RV24,RV32 conversions") ); + set_description( N_("I420,IYUV,YV12 to " + "RGB2,RV15,RV16,RV24,RV32 conversions") ); set_capability( "chroma", 80 ); #elif defined (MODULE_NAME_IS_i420_rgb_mmx) - set_description( _( "MMX I420,IYUV,YV12 to " + set_description( N_( "MMX I420,IYUV,YV12 to " "RV15,RV16,RV24,RV32 conversions") ); set_capability( "chroma", 100 ); add_requirement( MMX ); +#elif defined (MODULE_NAME_IS_i420_rgb_sse2) + set_description( N_( "SSE2 I420,IYUV,YV12 to " + "RV15,RV16,RV24,RV32 conversions") ); + set_capability( "chroma", 120 ); + add_requirement( SSE2 ); #endif set_callbacks( Activate, Deactivate ); vlc_module_end(); @@ -92,20 +111,83 @@ static int Activate( vlc_object_t *p_this ) { #if defined (MODULE_NAME_IS_i420_rgb) case VLC_FOURCC('R','G','B','2'): - p_vout->chroma.pf_convert = E_(I420_RGB8); + p_vout->chroma.pf_convert = I420_RGB8; break; #endif case VLC_FOURCC('R','V','1','5'): - p_vout->chroma.pf_convert = E_(I420_RGB15); - break; - case VLC_FOURCC('R','V','1','6'): - p_vout->chroma.pf_convert = E_(I420_RGB16); +#if ! defined (MODULE_NAME_IS_i420_rgb) + /* If we don't have support for the bitmasks, bail out */ + if( ( p_vout->output.i_rmask == 0x7c00 + && p_vout->output.i_gmask == 0x03e0 + && p_vout->output.i_bmask == 0x001f ) ) + { + /* R5G5B6 pixel format */ + msg_Dbg(p_this, "RGB pixel format is R5G5B5"); + p_vout->chroma.pf_convert = I420_R5G5B5; + } + else if( ( p_vout->output.i_rmask == 0xf800 + && p_vout->output.i_gmask == 0x07e0 + && p_vout->output.i_bmask == 0x001f ) ) + { + /* R5G6B5 pixel format */ + msg_Dbg(p_this, "RGB pixel format is R5G6B5"); + p_vout->chroma.pf_convert = I420_R5G6B5; + } + else + return -1; +#else + // generic C chroma converter */ + p_vout->chroma.pf_convert = I420_RGB16; +#endif break; +#if 0 + /* Hmmm, is there only X11 using 32bits per pixel for RV24 ? */ case VLC_FOURCC('R','V','2','4'): +#endif + case VLC_FOURCC('R','V','3','2'): - p_vout->chroma.pf_convert = E_(I420_RGB32); +#if ! defined (MODULE_NAME_IS_i420_rgb) + /* If we don't have support for the bitmasks, bail out */ + if( p_vout->output.i_rmask == 0x00ff0000 + && p_vout->output.i_gmask == 0x0000ff00 + && p_vout->output.i_bmask == 0x000000ff ) + { + /* A8R8G8B8 pixel format */ + msg_Dbg(p_this, "RGB pixel format is A8R8G8B8"); + p_vout->chroma.pf_convert = I420_A8R8G8B8; + } + else if( p_vout->output.i_rmask == 0xff000000 + && p_vout->output.i_gmask == 0x00ff0000 + && p_vout->output.i_bmask == 0x0000ff00 ) + { + /* R8G8B8A8 pixel format */ + msg_Dbg(p_this, "RGB pixel format is R8G8B8A8"); + p_vout->chroma.pf_convert = I420_R8G8B8A8; + } + else if( p_vout->output.i_rmask == 0x0000ff00 + && p_vout->output.i_gmask == 0x00ff0000 + && p_vout->output.i_bmask == 0xff000000 ) + { + /* B8G8R8A8 pixel format */ + msg_Dbg(p_this, "RGB pixel format is B8G8R8A8"); + p_vout->chroma.pf_convert = I420_B8G8R8A8; + } + else if( p_vout->output.i_rmask == 0x000000ff + && p_vout->output.i_gmask == 0x0000ff00 + && p_vout->output.i_bmask == 0x00ff0000 ) + { + /* A8B8G8R8 pixel format */ + msg_Dbg(p_this, "RGB pixel format is A8B8G8R8"); + p_vout->chroma.pf_convert = I420_A8B8G8R8; + } + else + return -1; +#else + /* generic C chroma converter */ + p_vout->chroma.pf_convert = I420_RGB32; +#endif break; default: @@ -116,7 +198,7 @@ static int Activate( vlc_object_t *p_this ) default: return -1; } - + p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) ); if( p_vout->chroma.p_sys == NULL ) { @@ -167,14 +249,14 @@ static int Activate( vlc_object_t *p_this ) switch( p_vout->output.i_chroma ) { case VLC_FOURCC('R','G','B','2'): - i_tables_size = sizeof( u8 ) * PALETTE_TABLE_SIZE; + i_tables_size = sizeof( uint8_t ) * PALETTE_TABLE_SIZE; break; case VLC_FOURCC('R','V','1','5'): case VLC_FOURCC('R','V','1','6'): - i_tables_size = sizeof( u16 ) * RGB_TABLE_SIZE; + i_tables_size = sizeof( uint16_t ) * RGB_TABLE_SIZE; break; default: /* RV24, RV32 */ - i_tables_size = sizeof( u32 ) * RGB_TABLE_SIZE; + i_tables_size = sizeof( uint32_t ) * RGB_TABLE_SIZE; break; } @@ -190,7 +272,7 @@ static int Activate( vlc_object_t *p_this ) SetYUV( p_vout ); #endif - return 0; + return 0; } /***************************************************************************** @@ -226,7 +308,7 @@ static void SetGammaTable( int *pi_table, double f_gamma ) /* Build gamma table */ for( i_y = 0; i_y < 256; i_y++ ) { - pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256; + pi_table[ i_y ] = (int)( pow( (double)i_y / 256, f_gamma ) * 256 ); } } @@ -235,8 +317,10 @@ static void SetGammaTable( int *pi_table, double f_gamma ) *****************************************************************************/ static void SetYUV( vout_thread_t *p_vout ) { - int pi_gamma[256]; /* gamma table */ - int i_index; /* index in tables */ + int pi_gamma[256]; /* gamma table */ + volatile int i_index; /* index in tables */ + /* We use volatile here to work around a strange gcc-3.3.4 + * optimization bug */ /* Build gamma table */ SetGammaTable( pi_gamma, p_vout->f_gamma ); @@ -249,13 +333,13 @@ static void SetYUV( vout_thread_t *p_vout ) switch( p_vout->output.i_chroma ) { case VLC_FOURCC('R','G','B','2'): - p_vout->chroma.p_sys->p_rgb8 = (u8 *)p_vout->chroma.p_sys->p_base; + p_vout->chroma.p_sys->p_rgb8 = (uint8_t *)p_vout->chroma.p_sys->p_base; Set8bppPalette( p_vout, p_vout->chroma.p_sys->p_rgb8 ); break; case VLC_FOURCC('R','V','1','5'): case VLC_FOURCC('R','V','1','6'): - p_vout->chroma.p_sys->p_rgb16 = (u16 *)p_vout->chroma.p_sys->p_base; + p_vout->chroma.p_sys->p_rgb16 = (uint16_t *)p_vout->chroma.p_sys->p_base; for( i_index = 0; i_index < RED_MARGIN; i_index++ ) { p_vout->chroma.p_sys->p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 ); @@ -281,7 +365,7 @@ static void SetYUV( vout_thread_t *p_vout ) case VLC_FOURCC('R','V','2','4'): case VLC_FOURCC('R','V','3','2'): - p_vout->chroma.p_sys->p_rgb32 = (u32 *)p_vout->chroma.p_sys->p_base; + p_vout->chroma.p_sys->p_rgb32 = (uint32_t *)p_vout->chroma.p_sys->p_base; for( i_index = 0; i_index < RED_MARGIN; i_index++ ) { p_vout->chroma.p_sys->p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 ); @@ -307,14 +391,17 @@ static void SetYUV( vout_thread_t *p_vout ) } } -static void Set8bppPalette( vout_thread_t *p_vout, u8 *p_rgb8 ) +static void Set8bppPalette( vout_thread_t *p_vout, uint8_t *p_rgb8 ) { #define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 ) int y,u,v; int r,g,b; int i = 0, j = 0; - u16 red[ 256 ], green[ 256 ], blue[ 256 ]; + uint16_t *p_cmap_r=p_vout->chroma.p_sys->p_rgb_r; + uint16_t *p_cmap_g=p_vout->chroma.p_sys->p_rgb_g; + uint16_t *p_cmap_b=p_vout->chroma.p_sys->p_rgb_b; + unsigned char p_lookup[PALETTE_TABLE_SIZE]; /* This loop calculates the intersection of an YUV box and the RGB cube. */ @@ -341,9 +428,15 @@ static void Set8bppPalette( vout_thread_t *p_vout, u8 *p_rgb8 ) } /* Clip the colors */ - red[ j ] = CLIP( r ); - green[ j ] = CLIP( g ); - blue[ j ] = CLIP( b ); + p_cmap_r[ j ] = CLIP( r ); + p_cmap_g[ j ] = CLIP( g ); + p_cmap_b[ j ] = CLIP( b ); + +#if 0 + printf("+++Alloc RGB cmap %d (%d, %d, %d)\n", j, + p_cmap_r[ j ] >>8, p_cmap_g[ j ] >>8, + p_cmap_b[ j ] >>8); +#endif /* Allocate color */ p_lookup[ i ] = 1; @@ -360,7 +453,7 @@ static void Set8bppPalette( vout_thread_t *p_vout, u8 *p_rgb8 ) } /* The colors have been allocated, we can set the palette */ - p_vout->output.pf_setpalette( p_vout, red, green, blue ); + p_vout->output.pf_setpalette( p_vout, p_cmap_r, p_cmap_g, p_cmap_b ); #if 0 /* There will eventually be a way to know which colors