00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <math.h>
00028 #include <string.h>
00029 #include <stdlib.h>
00030
00031 #include <vlc/vlc.h>
00032 #include <vlc/vout.h>
00033
00034 #include "i420_rgb.h"
00035 #if defined (MODULE_NAME_IS_i420_rgb)
00036 # include "i420_rgb_c.h"
00037 #endif
00038
00039
00040
00041
00042 #define RGB2PIXEL( p_vout, i_r, i_g, i_b ) \
00043 (((((uint32_t)i_r) >> p_vout->output.i_rrshift) \
00044 << p_vout->output.i_lrshift) \
00045 | ((((uint32_t)i_g) >> p_vout->output.i_rgshift) \
00046 << p_vout->output.i_lgshift) \
00047 | ((((uint32_t)i_b) >> p_vout->output.i_rbshift) \
00048 << p_vout->output.i_lbshift))
00049
00050
00051
00052
00053 static int Activate ( vlc_object_t * );
00054 static void Deactivate ( vlc_object_t * );
00055
00056 #if defined (MODULE_NAME_IS_i420_rgb)
00057 static void SetGammaTable ( int *pi_table, double f_gamma );
00058 static void SetYUV ( vout_thread_t * );
00059 static void Set8bppPalette ( vout_thread_t *, uint8_t * );
00060 #endif
00061
00062
00063
00064
00065 vlc_module_begin();
00066 #if defined (MODULE_NAME_IS_i420_rgb)
00067 set_description( _("I420,IYUV,YV12 to "
00068 "RGB2,RV15,RV16,RV24,RV32 conversions") );
00069 set_capability( "chroma", 80 );
00070 #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
00071 set_description( _( "MMX I420,IYUV,YV12 to "
00072 "RV15,RV16,RV24,RV32 conversions") );
00073 set_capability( "chroma", 100 );
00074 add_requirement( MMX );
00075 #endif
00076 set_callbacks( Activate, Deactivate );
00077 vlc_module_end();
00078
00079
00080
00081
00082
00083
00084 static int Activate( vlc_object_t *p_this )
00085 {
00086 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00087 #if defined (MODULE_NAME_IS_i420_rgb)
00088 size_t i_tables_size;
00089 #endif
00090
00091 if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
00092 {
00093 return -1;
00094 }
00095
00096 switch( p_vout->render.i_chroma )
00097 {
00098 case VLC_FOURCC('Y','V','1','2'):
00099 case VLC_FOURCC('I','4','2','0'):
00100 case VLC_FOURCC('I','Y','U','V'):
00101 switch( p_vout->output.i_chroma )
00102 {
00103 #if defined (MODULE_NAME_IS_i420_rgb)
00104 case VLC_FOURCC('R','G','B','2'):
00105 p_vout->chroma.pf_convert = E_(I420_RGB8);
00106 break;
00107 #endif
00108 case VLC_FOURCC('R','V','1','5'):
00109 case VLC_FOURCC('R','V','1','6'):
00110 #if defined (MODULE_NAME_IS_i420_rgb_mmx)
00111
00112 if( ( p_vout->output.i_rmask != 0x7c00
00113 || p_vout->output.i_gmask != 0x03e0
00114 || p_vout->output.i_bmask != 0x001f )
00115 && ( p_vout->output.i_rmask != 0xf800
00116 || p_vout->output.i_gmask != 0x07e0
00117 || p_vout->output.i_bmask != 0x001f ) )
00118 {
00119 return -1;
00120 }
00121 #endif
00122 p_vout->chroma.pf_convert = E_(I420_RGB16);
00123 break;
00124
00125 #if 0
00126
00127 case VLC_FOURCC('R','V','2','4'):
00128 #endif
00129
00130 case VLC_FOURCC('R','V','3','2'):
00131 #if defined (MODULE_NAME_IS_i420_rgb_mmx)
00132
00133 if( p_vout->output.i_rmask != 0x00ff0000
00134 || p_vout->output.i_gmask != 0x0000ff00
00135 || p_vout->output.i_bmask != 0x000000ff )
00136 {
00137 return -1;
00138 }
00139 #endif
00140 p_vout->chroma.pf_convert = E_(I420_RGB32);
00141 break;
00142
00143 default:
00144 return -1;
00145 }
00146 break;
00147
00148 default:
00149 return -1;
00150 }
00151
00152 p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) );
00153 if( p_vout->chroma.p_sys == NULL )
00154 {
00155 return -1;
00156 }
00157
00158 switch( p_vout->output.i_chroma )
00159 {
00160 #if defined (MODULE_NAME_IS_i420_rgb)
00161 case VLC_FOURCC('R','G','B','2'):
00162 p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH );
00163 break;
00164 #endif
00165
00166 case VLC_FOURCC('R','V','1','5'):
00167 case VLC_FOURCC('R','V','1','6'):
00168 p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH * 2 );
00169 break;
00170
00171 case VLC_FOURCC('R','V','2','4'):
00172 case VLC_FOURCC('R','V','3','2'):
00173 p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH * 4 );
00174 break;
00175
00176 default:
00177 p_vout->chroma.p_sys->p_buffer = NULL;
00178 break;
00179 }
00180
00181 if( p_vout->chroma.p_sys->p_buffer == NULL )
00182 {
00183 free( p_vout->chroma.p_sys );
00184 return -1;
00185 }
00186
00187 p_vout->chroma.p_sys->p_offset = malloc( p_vout->output.i_width
00188 * ( ( p_vout->output.i_chroma
00189 == VLC_FOURCC('R','G','B','2') ) ? 2 : 1 )
00190 * sizeof( int ) );
00191 if( p_vout->chroma.p_sys->p_offset == NULL )
00192 {
00193 free( p_vout->chroma.p_sys->p_buffer );
00194 free( p_vout->chroma.p_sys );
00195 return -1;
00196 }
00197
00198 #if defined (MODULE_NAME_IS_i420_rgb)
00199 switch( p_vout->output.i_chroma )
00200 {
00201 case VLC_FOURCC('R','G','B','2'):
00202 i_tables_size = sizeof( uint8_t ) * PALETTE_TABLE_SIZE;
00203 break;
00204 case VLC_FOURCC('R','V','1','5'):
00205 case VLC_FOURCC('R','V','1','6'):
00206 i_tables_size = sizeof( uint16_t ) * RGB_TABLE_SIZE;
00207 break;
00208 default:
00209 i_tables_size = sizeof( uint32_t ) * RGB_TABLE_SIZE;
00210 break;
00211 }
00212
00213 p_vout->chroma.p_sys->p_base = malloc( i_tables_size );
00214 if( p_vout->chroma.p_sys->p_base == NULL )
00215 {
00216 free( p_vout->chroma.p_sys->p_offset );
00217 free( p_vout->chroma.p_sys->p_buffer );
00218 free( p_vout->chroma.p_sys );
00219 return -1;
00220 }
00221
00222 SetYUV( p_vout );
00223 #endif
00224
00225 return 0;
00226 }
00227
00228
00229
00230
00231
00232
00233 static void Deactivate( vlc_object_t *p_this )
00234 {
00235 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00236
00237 #if defined (MODULE_NAME_IS_i420_rgb)
00238 free( p_vout->chroma.p_sys->p_base );
00239 #endif
00240 free( p_vout->chroma.p_sys->p_offset );
00241 free( p_vout->chroma.p_sys->p_buffer );
00242 free( p_vout->chroma.p_sys );
00243 }
00244
00245 #if defined (MODULE_NAME_IS_i420_rgb)
00246
00247
00248
00249
00250
00251 static void SetGammaTable( int *pi_table, double f_gamma )
00252 {
00253 int i_y;
00254
00255
00256 f_gamma = exp( f_gamma );
00257
00258
00259 for( i_y = 0; i_y < 256; i_y++ )
00260 {
00261 pi_table[ i_y ] = (int)( pow( (double)i_y / 256, f_gamma ) * 256 );
00262 }
00263 }
00264
00265
00266
00267
00268 static void SetYUV( vout_thread_t *p_vout )
00269 {
00270 int pi_gamma[256];
00271 volatile int i_index;
00272
00273
00274
00275
00276 SetGammaTable( pi_gamma, p_vout->f_gamma );
00277
00278
00279
00280
00281
00282
00283 switch( p_vout->output.i_chroma )
00284 {
00285 case VLC_FOURCC('R','G','B','2'):
00286 p_vout->chroma.p_sys->p_rgb8 = (uint8_t *)p_vout->chroma.p_sys->p_base;
00287 Set8bppPalette( p_vout, p_vout->chroma.p_sys->p_rgb8 );
00288 break;
00289
00290 case VLC_FOURCC('R','V','1','5'):
00291 case VLC_FOURCC('R','V','1','6'):
00292 p_vout->chroma.p_sys->p_rgb16 = (uint16_t *)p_vout->chroma.p_sys->p_base;
00293 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
00294 {
00295 p_vout->chroma.p_sys->p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
00296 p_vout->chroma.p_sys->p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
00297 }
00298 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
00299 {
00300 p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
00301 p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
00302 }
00303 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
00304 {
00305 p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
00306 p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
00307 }
00308 for( i_index = 0; i_index < 256; i_index++ )
00309 {
00310 p_vout->chroma.p_sys->p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
00311 p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
00312 p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
00313 }
00314 break;
00315
00316 case VLC_FOURCC('R','V','2','4'):
00317 case VLC_FOURCC('R','V','3','2'):
00318 p_vout->chroma.p_sys->p_rgb32 = (uint32_t *)p_vout->chroma.p_sys->p_base;
00319 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
00320 {
00321 p_vout->chroma.p_sys->p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
00322 p_vout->chroma.p_sys->p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
00323 }
00324 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
00325 {
00326 p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
00327 p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
00328 }
00329 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
00330 {
00331 p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
00332 p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
00333 }
00334 for( i_index = 0; i_index < 256; i_index++ )
00335 {
00336 p_vout->chroma.p_sys->p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
00337 p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
00338 p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
00339 }
00340 break;
00341 }
00342 }
00343
00344 static void Set8bppPalette( vout_thread_t *p_vout, uint8_t *p_rgb8 )
00345 {
00346 #define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 )
00347
00348 int y,u,v;
00349 int r,g,b;
00350 int i = 0, j = 0;
00351 uint16_t *p_cmap_r=p_vout->chroma.p_sys->p_rgb_r;
00352 uint16_t *p_cmap_g=p_vout->chroma.p_sys->p_rgb_g;
00353 uint16_t *p_cmap_b=p_vout->chroma.p_sys->p_rgb_b;
00354
00355 unsigned char p_lookup[PALETTE_TABLE_SIZE];
00356
00357
00358 for ( y = 0; y <= 256; y += 16, i += 128 - 81 )
00359 {
00360 for ( u = 0; u <= 256; u += 32 )
00361 {
00362 for ( v = 0; v <= 256; v += 32 )
00363 {
00364 r = y + ( (V_RED_COEF*(v-128)) >> SHIFT );
00365 g = y + ( (U_GREEN_COEF*(u-128)
00366 + V_GREEN_COEF*(v-128)) >> SHIFT );
00367 b = y + ( (U_BLUE_COEF*(u-128)) >> SHIFT );
00368
00369 if( r >= 0x00 && g >= 0x00 && b >= 0x00
00370 && r <= 0xff && g <= 0xff && b <= 0xff )
00371 {
00372
00373
00374 if( j == 256 )
00375 {
00376 msg_Err( p_vout, "no colors left in palette" );
00377 break;
00378 }
00379
00380
00381 p_cmap_r[ j ] = CLIP( r );
00382 p_cmap_g[ j ] = CLIP( g );
00383 p_cmap_b[ j ] = CLIP( b );
00384
00385 #if 0
00386 printf("+++Alloc RGB cmap %d (%d, %d, %d)\n", j,
00387 p_cmap_r[ j ] >>8, p_cmap_g[ j ] >>8,
00388 p_cmap_b[ j ] >>8);
00389 #endif
00390
00391
00392 p_lookup[ i ] = 1;
00393 p_rgb8[ i++ ] = j;
00394 j++;
00395 }
00396 else
00397 {
00398 p_lookup[ i ] = 0;
00399 p_rgb8[ i++ ] = 0;
00400 }
00401 }
00402 }
00403 }
00404
00405
00406 p_vout->output.pf_setpalette( p_vout, p_cmap_r, p_cmap_g, p_cmap_b );
00407
00408 #if 0
00409
00410
00411 p_vout->i_white_pixel = 0xff;
00412 p_vout->i_black_pixel = 0x00;
00413 p_vout->i_gray_pixel = 0x44;
00414 p_vout->i_blue_pixel = 0x3b;
00415 #endif
00416
00417
00418 for ( i = 0, y = 0; y <= 256; y += 16, i += 128 - 81 )
00419 {
00420 for ( u = 0; u <= 256; u += 32 )
00421 {
00422 for ( v = 0; v <= 256; v += 32, i++ )
00423 {
00424 int u2, v2, dist, mindist = 100000000;
00425
00426 if( p_lookup[ i ] || y == 0 )
00427 {
00428 continue;
00429 }
00430
00431
00432 for( u2 = 0; u2 <= 256; u2 += 32 )
00433 {
00434 for( v2 = 0; v2 <= 256; v2 += 32 )
00435 {
00436 j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
00437 dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
00438
00439
00440 if( p_lookup[ j ] && dist < mindist )
00441 {
00442 p_rgb8[ i ] = p_rgb8[ j ];
00443 mindist = dist;
00444 }
00445
00446 j -= 128;
00447
00448
00449 if( p_lookup[ j ] && dist + 128 < mindist )
00450 {
00451 p_rgb8[ i ] = p_rgb8[ j ];
00452 mindist = dist + 128;
00453 }
00454 }
00455 }
00456 }
00457 }
00458 }
00459 }
00460
00461 #endif
00462