]> git.sesse.net Git - vlc/blob - src/video_output/video_yuv.c
Suppression de la ligne verte.
[vlc] / src / video_output / video_yuv.c
1 /*******************************************************************************
2  * video_yuv.c: YUV transformation functions
3  * (c)1999 VideoLAN
4  *******************************************************************************
5  * Provides functions to perform the YUV conversion. The functions provided here
6  * are a complete and portable C implementation, and may be replaced in certain
7  * case by optimized functions.
8  *******************************************************************************/
9
10 /*******************************************************************************
11  * Preamble
12  *******************************************************************************/
13 #include <math.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <stdlib.h>
17
18 #include "common.h"
19 #include "config.h"
20 #include "mtime.h"
21 #include "vlc_thread.h"
22 #include "video.h"
23 #include "video_output.h"
24 #include "video_yuv.h"
25 #include "intf_msg.h"
26
27 /*******************************************************************************
28  * Constants
29  *******************************************************************************/
30
31 /* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
32 const int MATRIX_COEFFICIENTS_TABLE[8][4] =
33 {
34   {117504, 138453, 13954, 34903},       /* no sequence_display_extension */
35   {117504, 138453, 13954, 34903},       /* ITU-R Rec. 709 (1990) */
36   {104597, 132201, 25675, 53279},       /* unspecified */
37   {104597, 132201, 25675, 53279},       /* reserved */
38   {104448, 132798, 24759, 53109},       /* FCC */
39   {104597, 132201, 25675, 53279},       /* ITU-R Rec. 624-4 System B, G */
40   {104597, 132201, 25675, 53279},       /* SMPTE 170M */
41   {117579, 136230, 16907, 35559}        /* SMPTE 240M (1987) */
42 };
43
44 /* Margins in convertion tables - these margins are used in case a RGB convertion
45  * would give a value outside the 0-255 range. */
46 #define RED_MARGIN      178
47 #define GREEN_MARGIN    135
48 #define BLUE_MARGIN     224
49 #define GRAY_MARGIN     384
50
51 //??
52 #define SHIFT 20
53 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
54 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
55 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
56 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
57
58 /*******************************************************************************
59  * Local prototypes
60  *******************************************************************************/
61 static int      BinaryLog         ( u32 i );
62 static void     MaskToShift       ( int *pi_right, int *pi_left, u32 i_mask );
63 static void     SetGammaTable     ( int *pi_table, double f_gamma );
64 static void     SetYUV            ( vout_thread_t *p_vout );
65
66 static void     ConvertY4Gray16   ( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
67                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
68                                     int i_matrix_coefficients );
69 static void     ConvertY4Gray24   ( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
70                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
71                                     int i_matrix_coefficients );
72 static void     ConvertY4Gray32   ( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
73                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
74                                     int i_matrix_coefficients );
75 static void     ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
76                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
77                                     int i_matrix_coefficients );
78 static void     ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
79                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
80                                     int i_matrix_coefficients );
81 static void     ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
82                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
83                                     int i_matrix_coefficients );
84 static void     ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
85                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
86                                     int i_matrix_coefficients );
87 static void     ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
88                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
89                                     int i_matrix_coefficients );
90 static void     ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
91                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
92                                     int i_matrix_coefficients );
93 static void     ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
94                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
95                                     int i_matrix_coefficients );
96 static void     ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
97                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
98                                     int i_matrix_coefficients );
99 static void     ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
100                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
101                                     int i_matrix_coefficients );
102
103 /*******************************************************************************
104  * CLIP_BYTE macro: boundary detection
105  *******************************************************************************
106  * Return parameter if between 0 and 255, else return nearest boundary (0 or 
107  * 255). This macro is used to build translations tables.
108  *******************************************************************************/
109 #define CLIP_BYTE( i_val ) ( (i_val < 0) ? 0 : ((i_val > 255) ? 255 : i_val) )
110
111 /*******************************************************************************
112  * CONVERT_YUV_GRAY macro: grayscale YUV convertion
113  *******************************************************************************
114  * This macro does not perform any scaling, but crops the picture. It is
115  * provided as a temporary way of implementing an YUV convertion function.
116  *******************************************************************************/
117 #define CONVERT_YUV_GRAY                                                \
118 /* Change boundaries according to picture size */                       \
119 i_width =               MIN( i_width, i_pic_width );                    \
120 i_height =              MIN( i_height, i_pic_height );                  \
121 i_pic_line_width -=     i_width;                                        \
122                                                                         \
123 /* Loop */                                                              \
124 for (i_y = 0; i_y < i_height ; i_y++)                                   \
125 {                                                                       \
126     for (i_x = 0; i_x < i_width; )                                      \
127     {                                                                   \
128         /* Convert 16 pixels (width is always multiple of 16 */         \
129         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
130         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
131         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
132         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
133         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
134         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
135         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
136         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
137         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
138         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
139         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
140         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
141         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
142         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
143         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
144         p_pic[i_x++] = p_gray[ p_y[i_x] ];                              \
145     }                                                                   \
146                                                                         \
147     /* Skip until beginning of next line */                             \
148     p_pic += i_pic_line_width;                                          \
149 }
150
151 /*******************************************************************************
152  * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel convertion blocks
153  *******************************************************************************
154  * These convertion routines are used by YUV convertion functions.
155  * Convertion are made from p_y, p_u, p_v, which are modified, to p_buffer,
156  * which is also modified.
157  *******************************************************************************/
158 #define CONVERT_Y_PIXEL                                                         \
159     /* Only Y sample is present */                                              \
160     p_ybase = p_yuv + *(p_y++);                                                 \
161     *p_buffer++ = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |           \
162         p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |  \
163         p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];                     \
164
165 #define CONVERT_YUV_PIXEL                                                       \
166     /* Y, U and V samples are present */                                        \
167     i_uval =    *p_u++;                                                         \
168     i_vval =    *p_v++;                                                         \
169     i_red =     (V_RED_COEF * i_vval) >> SHIFT;                                 \
170     i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;       \
171     i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                                \
172     CONVERT_Y_PIXEL                                                             \
173
174 /*******************************************************************************
175  * vout_InitYUV: allocate and initialize translations tables
176  *******************************************************************************
177  * This function will allocate memory to store translation tables, depending
178  * of the screen depth.
179  *******************************************************************************/
180 int vout_InitYUV( vout_thread_t *p_vout )
181 {
182     size_t      tables_size;                          /* tables size, in bytes */
183     
184     /* Computes tables size */
185     switch( p_vout->i_screen_depth )
186     {
187     case 15:
188     case 16:
189         tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? 1034 : 1935);
190         break;        
191     case 24:        
192     case 32:
193 #ifndef DEBUG
194     default:        
195 #endif
196         tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? 1024 : 1935);        
197         break;        
198 #ifdef DEBUG
199     default:
200         intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
201         tables_size = 0;
202         break;        
203 #endif      
204     }
205     
206     /* Allocate memory */
207     p_vout->yuv.p_base = malloc( tables_size );
208     if( p_vout->yuv.p_base == NULL )
209     {
210         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
211         return( 1 );                
212     }
213
214     /* Allocate memory for convertion buffer and offset array */
215     p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
216     if( p_vout->yuv.p_buffer == NULL )
217     {
218         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
219         free( p_vout->yuv.p_base );
220         return( 1 );                
221     }
222     p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );    
223     if( p_vout->yuv.p_offset == NULL )
224     {
225         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
226         free( p_vout->yuv.p_base );
227         free( p_vout->yuv.p_buffer );        
228         return( 1 );                
229     }
230
231     /* Initialize tables */
232     SetYUV( p_vout );
233     return( 0 );    
234 }
235
236 /*******************************************************************************
237  * vout_ResetTables: re-initialize translations tables
238  *******************************************************************************
239  * This function will initialize the tables allocated by vout_CreateTables and
240  * set functions pointers.
241  *******************************************************************************/
242 int vout_ResetYUV( vout_thread_t *p_vout )
243 {
244     vout_EndYUV( p_vout );    
245     return( vout_InitYUV( p_vout ) );    
246 }
247
248 /*******************************************************************************
249  * vout_EndYUV: destroy translations tables
250  *******************************************************************************
251  * Free memory allocated by vout_CreateTables.
252  *******************************************************************************/
253 void vout_EndYUV( vout_thread_t *p_vout )
254 {
255     free( p_vout->yuv.p_base );
256     free( p_vout->yuv.p_buffer );
257     free( p_vout->yuv.p_offset );    
258 }
259
260 /* following functions are local */
261
262 /*******************************************************************************
263  * BinaryLog: computes the base 2 log of a binary value
264  *******************************************************************************
265  * This functions is used by MaskToShift during tables initialisation, to
266  * get a bit index from a binary value.
267  *******************************************************************************/
268 static int BinaryLog(u32 i)
269 {
270     int i_log;
271
272     i_log = 0;
273     if (i & 0xffff0000) 
274     {        
275         i_log = 16;
276     }    
277     if (i & 0xff00ff00) 
278     {        
279         i_log += 8;
280     }    
281     if (i & 0xf0f0f0f0) 
282     {        
283         i_log += 4;
284     }    
285     if (i & 0xcccccccc) 
286     {        
287         i_log += 2;
288     }    
289     if (i & 0xaaaaaaaa) 
290     {        
291         i_log++;
292     }    
293     if (i != ((u32)1 << i_log))
294     {        
295         intf_ErrMsg("internal error: binary log overflow\n");        
296     }    
297
298     return( i_log );
299 }
300
301 /*******************************************************************************
302  * MaskToShift: Transform a color mask into right and left shifts
303  *******************************************************************************
304  * This function is used during table initialisation. It can return a value
305  *******************************************************************************/
306 static void MaskToShift (int *pi_right, int *pi_left, u32 i_mask)
307 {
308     u32 i_low, i_high;                   /* lower hand higher bits of the mask */
309
310     /* Get bits */
311     i_low =  i_mask & (- i_mask);                     /* lower bit of the mask */
312     i_high = i_mask + i_low;                         /* higher bit of the mask */
313
314     /* Transform bits into an index */
315     i_low =  BinaryLog (i_low);
316     i_high = BinaryLog (i_high);
317
318     /* Update pointers and return */
319     *pi_left =   i_low;
320     *pi_right = (8 - i_high + i_low);
321 }
322
323 /*******************************************************************************
324  * SetGammaTable: return intensity table transformed by gamma curve.
325  *******************************************************************************
326  * pi_table is a table of 256 entries from 0 to 255.
327  *******************************************************************************/
328 static void SetGammaTable( int *pi_table, double f_gamma )
329 {
330     int         i_y;                                         /* base intensity */
331
332     /* Use exp(gamma) instead of gamma */
333     f_gamma = exp(f_gamma );
334
335     /* Build gamma table */
336     for( i_y = 0; i_y < 256; i_y++ )
337     {
338         pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
339     }
340  }
341
342 /*******************************************************************************
343  * SetYUV: compute tables and set function pointers
344 + *******************************************************************************/
345 static void SetYUV( vout_thread_t *p_vout )
346 {
347     int         pi_gamma[256];                                  /* gamma table */    
348     int         i_index;                                    /* index in tables */
349     int         i_red_right, i_red_left;                         /* red shifts */
350     int         i_green_right, i_green_left;                   /* green shifts */
351     int         i_blue_right, i_blue_left;                      /* blue shifts */
352
353     /* Build gamma table */    
354     SetGammaTable( pi_gamma, p_vout->f_gamma );
355     
356     /*          
357      * Set color masks and shifts
358      */
359     switch( p_vout->i_screen_depth )
360     {
361     case 15:
362         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
363         MaskToShift( &i_green_right, &i_green_left, 0x03e0 );
364         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );        
365         break;        
366     case 16:
367         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
368         MaskToShift( &i_green_right, &i_green_left, 0x07e0 );
369         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );
370         break;        
371     case 24:
372     case 32:        
373         MaskToShift( &i_red_right,   &i_red_left,   0x00ff0000 );
374         MaskToShift( &i_green_right, &i_green_left, 0x0000ff00 );
375         MaskToShift( &i_blue_right,  &i_blue_left,  0x000000ff );
376         break;
377 #ifdef DEBUG
378     default:
379         intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
380         break;        
381 #endif      
382     }
383
384     /*
385      * Set pointers and build YUV tables
386      */        
387     if( p_vout->b_grayscale )
388     {
389         /* Grayscale: build gray table */
390         switch( p_vout->i_screen_depth )
391         {
392         case 15:
393         case 16:         
394             p_vout->yuv.yuv.p_gray16 =  (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
395             for( i_index = -GRAY_MARGIN; i_index < 256 + GRAY_MARGIN; i_index++) 
396             {
397                 p_vout->yuv.yuv.p_gray16[ i_index ] = 
398                     ((pi_gamma[CLIP_BYTE( i_index )] >> i_red_right)   << i_red_left)   |
399                     ((pi_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) |
400                     ((pi_gamma[CLIP_BYTE( i_index )] >> i_blue_right)  << i_blue_left);
401             }
402             break;        
403         case 24:
404         case 32:        
405             p_vout->yuv.yuv.p_gray32 =  (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
406             for( i_index = -GRAY_MARGIN; i_index < 256 + GRAY_MARGIN; i_index++) 
407             {
408                 p_vout->yuv.yuv.p_gray32[ i_index ] = 
409                     ((pi_gamma[CLIP_BYTE( i_index )] >> i_red_right)   << i_red_left)   |
410                     ((pi_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) |
411                     ((pi_gamma[CLIP_BYTE( i_index )] >> i_blue_right)  << i_blue_left);
412             }        
413             break;        
414         }
415     }
416     else
417     {
418         /* Color: build red, green and blue tables */
419         switch( p_vout->i_screen_depth )
420         {
421         case 15:
422         case 16:            
423             p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
424             for( i_index = 0; i_index < RED_MARGIN; i_index++ )
425             {
426                 p_vout->yuv.yuv.p_rgb16[1501 - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
427                 p_vout->yuv.yuv.p_rgb16[1501 + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;                
428             }
429             for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
430             {
431                 p_vout->yuv.yuv.p_rgb16[135 - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right)<<i_green_left;
432                 p_vout->yuv.yuv.p_rgb16[135 + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
433             }
434             for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
435             {
436                 p_vout->yuv.yuv.p_rgb16[818 - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
437                 p_vout->yuv.yuv.p_rgb16[818 + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;                
438             }
439             for( i_index = 0; i_index < 256; i_index++ )
440             {
441                 p_vout->yuv.yuv.p_rgb16[1501 + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
442                 p_vout->yuv.yuv.p_rgb16[135 + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
443                 p_vout->yuv.yuv.p_rgb16[818 + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
444             }            
445             break;        
446         case 24:
447         case 32:
448             p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
449             for( i_index = 0; i_index < RED_MARGIN; i_index++ )
450             {
451                 p_vout->yuv.yuv.p_rgb32[1501 - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
452                 p_vout->yuv.yuv.p_rgb32[1501 + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;                
453             }
454             for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
455             {
456                 p_vout->yuv.yuv.p_rgb32[135 - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right)<<i_green_left;
457                 p_vout->yuv.yuv.p_rgb32[135 + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
458             }
459             for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
460             {
461                 p_vout->yuv.yuv.p_rgb32[818 - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
462                 p_vout->yuv.yuv.p_rgb32[818 + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;                
463             }
464             for( i_index = 0; i_index < 256; i_index++ )
465             {
466                 p_vout->yuv.yuv.p_rgb32[1501 + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
467                 p_vout->yuv.yuv.p_rgb32[135 + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
468                 p_vout->yuv.yuv.p_rgb32[818 + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
469             }            
470             break;        
471         }
472     }    
473
474     /*
475      * Set functions pointers
476      */
477     if( p_vout->b_grayscale )
478     {
479         /* Grayscale */
480         switch( p_vout->i_screen_depth )
481         {
482         case 15:
483         case 16:  
484             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;        
485             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;        
486             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;        
487             break;        
488         case 24:
489             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;        
490             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;        
491             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;        
492             break;        
493         case 32:        
494             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;        
495             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;        
496             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;        
497             break;        
498         }        
499     }
500     else
501     {
502         /* Color */
503         switch( p_vout->i_screen_depth )
504         {
505         case 15:
506         case 16:  
507             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB16;        
508             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB16;        
509             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB16;        
510             break;        
511         case 24:
512             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB24;        
513             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB24;        
514             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB24;        
515             break;        
516         case 32:        
517             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB32;        
518             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB32;        
519             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB32;        
520             break;        
521         }
522     }        
523 }
524
525 /*******************************************************************************
526  * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 15 or 16 bpp
527  *******************************************************************************/
528 static void ConvertY4Gray16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
529                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
530                              int i_matrix_coefficients )
531 {
532     u16 *       p_gray;                                          /* gray table */    
533     int         i_x, i_y;                               /* picture coordinates */
534     
535     p_gray = p_vout->yuv.yuv.p_gray16;    
536     CONVERT_YUV_GRAY
537 }
538
539 /*******************************************************************************
540  * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 24 bpp
541  *******************************************************************************/
542 static void ConvertY4Gray24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
543                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
544                              int i_matrix_coefficients )
545 {
546     //??
547 }
548
549 /*******************************************************************************
550  * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 32 bpp
551  *******************************************************************************/
552 static void ConvertY4Gray32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
553                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
554                              int i_matrix_coefficients )
555 {
556     u32 *       p_gray;                                          /* gray table */    
557     int         i_x, i_y;                               /* picture coordinates */
558     
559     p_gray = p_vout->yuv.yuv.p_gray32;
560     CONVERT_YUV_GRAY
561 }
562
563 /*******************************************************************************
564  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 15 or 16 bpp
565  *******************************************************************************/
566 static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
567                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
568                                 int i_matrix_coefficients )
569 {
570 /* MMX version */
571   //  int                 i_chroma_width, i_chroma_skip;      /* width and eol for chroma */
572 /*
573     i_chroma_width =    i_width / 2;
574     i_chroma_skip =     i_skip / 2;
575     ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height, 
576                            (i_width + i_skip) * sizeof( yuv_data_t ), 
577                            (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
578                            i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
579                            p_vout->i_screen_depth == 15 );    
580 */
581     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
582     int         i_vertical_scaling;                   /* vertical scaling type */
583     int         i_x, i_y;                   /* horizontal and vertical indexes */
584     int         i_scale_count;                         /* scale modulo counter */
585     int         i_uval, i_vval;                             /* U and V samples */
586     int         i_red, i_green, i_blue;            /* U and V modified samples */
587     int         i_chroma_width;                                /* chroma width */
588     u16 *       p_yuv;                                /* base convertion table */
589     u16 *       p_ybase;                       /* Y dependant convertion table */   
590     u16 *       p_pic_start;         /* beginning of the current line for copy */
591     u16 *       p_buffer_start;                     /* convertion buffer start */
592     u16 *       p_buffer;                         /* convertion buffer pointer */
593     int *       p_offset_start;                          /* offset array start */
594     int *       p_offset;                              /* offset array pointer */
595     
596     /* 
597      * Initialize some values  - i_pic_line_width will store the line skip 
598      */
599     i_pic_line_width -= i_pic_width;
600     i_chroma_width =    i_width / 2;
601     p_yuv =             p_vout->yuv.yuv.p_rgb16;
602    
603     /* 
604      * Set scalings 
605      */
606     if( i_pic_width - i_width > 0 )
607     {
608         /* Prepare scaling array for horizontal extension */
609         b_horizontal_scaling =  1;   
610         p_buffer_start =        p_vout->yuv.p_buffer;        
611         p_offset_start =        p_vout->yuv.p_offset;                    
612         p_offset =              p_offset_start;
613         i_scale_count =         i_pic_width;
614         for( i_x = i_width; i_x--; )
615         {
616             while( (i_scale_count -= i_width) > 0 )
617             {
618                 *p_offset++ = 0;                
619             }
620             *p_offset++ = 1;            
621             i_scale_count += i_pic_width;            
622         }        
623     }
624     else if( i_pic_width - i_width < 0 )
625     {
626         /* Prepare scaling array for horizontal reduction */
627         b_horizontal_scaling =  1;
628         p_buffer_start =        p_vout->yuv.p_buffer;
629         p_offset_start =        p_vout->yuv.p_offset;                    
630         p_offset =              p_offset_start;        
631         i_scale_count =         i_pic_width;
632         for( i_x = i_pic_width; i_x--; )
633         {
634             *p_offset = 1;            
635             while( (i_scale_count -= i_pic_width) >= 0 )
636             {                
637                 *p_offset += 1;                
638             }
639             p_offset++;
640             i_scale_count += i_width;
641         }        
642     }
643     else
644     {
645         /* No horizontal scaling: YUV convertion is done directly to picture */          
646         b_horizontal_scaling = 0;        
647         p_buffer_start = p_pic;                
648         p_offset_start = NULL;                             /* to avoid warning */
649     }
650     if( i_pic_height - i_height > 0 )
651     {
652         i_vertical_scaling = 1;        
653     }
654     else if( i_pic_height - i_height < 0 )
655     {
656         i_vertical_scaling = -1;        
657     }
658     else
659     {
660         i_vertical_scaling = 0;        
661     }
662
663     /*
664      * Perform convertion
665      */
666     i_scale_count = i_pic_height;
667     for( i_y = 0; i_y < i_height; i_y++ )
668     {
669         /* Mark beginnning of line for possible later line copy, and initialize
670          * buffer */
671         p_pic_start =   p_pic;
672         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
673
674         /* Do YUV convertion to buffer - YUV picture is always formed of 16
675          * pixels wide blocks */
676         for( i_x = i_width / 16; i_x--;  )
677         {
678             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
679             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
680             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
681             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
682             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
683             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
684             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
685             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
686         }             
687
688         if( b_horizontal_scaling )
689         {
690             /* Horizontal scaling, convertion has been done to buffer.
691              * Rewind buffer and offset, then copy and scale line */
692             p_buffer = p_buffer_start;
693             p_offset = p_offset_start;            
694             for( i_x = i_pic_width / 16; i_x--; )
695             {
696                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
697                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
698                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
699                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
700                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
701                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
702                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
703                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
704                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
705                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
706                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
707                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
708                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
709                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
710                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
711                 *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                
712             }            
713         }        
714         else
715         {
716             /* No scaling, convertion has been done directly in picture memory.
717              * Increment of picture pointer to end of line is still needed */
718             p_pic += i_pic_width;            
719         }
720
721         /* If line is odd, rewind U and V samples */
722         if( !(i_y & 0x1) )
723         {
724             p_u -= i_chroma_width;
725             p_v -= i_chroma_width;
726         }
727
728         /* End of line: skip picture to reach beginning of next line */
729         p_pic += i_pic_line_width;
730  
731         /* 
732          * Handle vertical scaling. The current line can be copied or next one
733          * can be ignored.
734          */
735         switch( i_vertical_scaling )
736         {
737         case -1:                         /* vertical scaling factor is < 1 */
738             while( (i_scale_count -= i_pic_height) >= 0 )
739             {                
740                 /* Height reduction: skip next source line */
741                 p_y += i_width;
742                 if( ++i_y & 0x1 )
743                 {
744                     p_u += i_chroma_width;
745                     p_v += i_chroma_width;
746                 }                
747             }            
748             i_scale_count += i_height;
749             break;            
750         case 1:                          /* vertical scaling factor is > 1 */
751             while( (i_scale_count -= i_height) > 0 )
752             {                
753                 /* Height increment: copy previous picture line */
754                 for( i_x = i_pic_width / 16; i_x--; )
755                 {
756                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
757                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
758                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
759                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
760                 }
761                 p_pic +=        i_pic_line_width;
762                 p_pic_start +=  i_pic_line_width;
763             }
764             i_scale_count += i_pic_height; 
765             break;
766         }
767     }
768 }
769
770 /*******************************************************************************
771  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 15 or 16 bpp
772  *******************************************************************************/
773 static void ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
774                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
775                                 int i_matrix_coefficients )
776 {
777     //??
778 }
779
780 /*******************************************************************************
781  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 15 or 16 bpp
782  *******************************************************************************/
783 static void ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
784                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
785                                 int i_matrix_coefficients )
786 {
787     //??
788 }
789
790 /*******************************************************************************
791  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 24 bpp
792  *******************************************************************************/
793 static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
794                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
795                                 int i_matrix_coefficients )
796 {
797     //???
798 }
799
800 /*******************************************************************************
801  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 24 bpp
802  *******************************************************************************/
803 static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
804                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
805                                 int i_matrix_coefficients )
806 {
807     //???
808 }
809
810 /*******************************************************************************
811  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 24 bpp
812  *******************************************************************************/
813 static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
814                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
815                                 int i_matrix_coefficients )
816 {    
817     //???
818 }
819
820 /*******************************************************************************
821  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 32 bpp
822  *******************************************************************************/
823 static void ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
824                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
825                                 int i_matrix_coefficients )
826 {
827     //??
828 }
829
830 /*******************************************************************************
831  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 32 bpp
832  *******************************************************************************/
833 static void ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
834                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
835                                 int i_matrix_coefficients )
836 {
837     //??
838 }
839
840 /*******************************************************************************
841  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 32 bpp
842  *******************************************************************************/
843 static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
844                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
845                                 int i_matrix_coefficients )
846 {
847     //??
848 }
849
850 //-------------------- walken code follow ---------------------------------------
851
852 /*
853  * YUV to RGB routines.
854  *
855  * these routines calculate r, g and b values from each pixel's y, u and v.
856  * these r, g an b values are then passed thru a table lookup to take the
857  * gamma curve into account and find the corresponding pixel value.
858  *
859  * the table must store more than 3*256 values because of the possibility
860  * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
861  * values are in the following intervals :
862  * -176 to 255+176 for red
863  * -133 to 255+133 for green
864  * -222 to 255+222 for blue
865  *
866  * If the input y,u,v values are right, the r,g,b results are not expected
867  * to move out of the 0 to 255 interval but who knows what will happen in
868  * real use...
869  *
870  * the red, green and blue conversion tables are stored in a single 1935-entry
871  * array. The respective positions of each component in the array have been
872  * calculated to minimize the cache interactions of the 3 tables.
873  */
874
875 static void yuvToRgb24 (unsigned char * Y,
876                         unsigned char * U, unsigned char * V,
877                         char * dest, int table[1935], int width)
878 {
879     int i;
880     int u;
881     int v;
882     int uvRed;
883     int uvGreen;
884     int uvBlue;
885     int * tableY;
886     int tmp24;
887
888     i = width >> 3;
889     while (i--) {
890         u = *(U++);
891         v = *(V++);
892         uvRed = (V_RED_COEF*v) >> SHIFT;
893         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
894         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
895
896         tableY = table + *(Y++);
897         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
898                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
899                         uvGreen] |
900                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
901         *(dest++) = tmp24;
902         *(dest++) = tmp24 >> 8;
903         *(dest++) = tmp24 >> 16;
904
905         tableY = table + *(Y++);
906         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
907                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
908                         uvGreen] |
909                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
910         *(dest++) = tmp24;
911         *(dest++) = tmp24 >> 8;
912         *(dest++) = tmp24 >> 16;
913
914         u = *(U++);
915         v = *(V++);
916         uvRed = (V_RED_COEF*v) >> SHIFT;
917         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
918         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
919
920         tableY = table + *(Y++);
921         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
922                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
923                         uvGreen] |
924                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
925         *(dest++) = tmp24;
926         *(dest++) = tmp24 >> 8;
927         *(dest++) = tmp24 >> 16;
928
929         tableY = table + *(Y++);
930         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
931                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
932                         uvGreen] |
933                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
934         *(dest++) = tmp24;
935         *(dest++) = tmp24 >> 8;
936         *(dest++) = tmp24 >> 16;
937
938         u = *(U++);
939         v = *(V++);
940         uvRed = (V_RED_COEF*v) >> SHIFT;
941         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
942         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
943
944         tableY = table + *(Y++);
945         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
946                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
947                         uvGreen] |
948                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
949         *(dest++) = tmp24;
950         *(dest++) = tmp24 >> 8;
951         *(dest++) = tmp24 >> 16;
952
953         tableY = table + *(Y++);
954         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
955                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
956                         uvGreen] |
957                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
958         *(dest++) = tmp24;
959         *(dest++) = tmp24 >> 8;
960         *(dest++) = tmp24 >> 16;
961
962         u = *(U++);
963         v = *(V++);
964         uvRed = (V_RED_COEF*v) >> SHIFT;
965         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
966         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
967
968         tableY = table + *(Y++);
969         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
970                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
971                         uvGreen] |
972                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
973         *(dest++) = tmp24;
974         *(dest++) = tmp24 >> 8;
975         *(dest++) = tmp24 >> 16;
976
977         tableY = table + *(Y++);
978         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
979                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
980                         uvGreen] |
981                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
982         *(dest++) = tmp24;
983         *(dest++) = tmp24 >> 8;
984         *(dest++) = tmp24 >> 16;
985     }
986
987     i = (width & 7) >> 1;
988     while (i--) {
989         u = *(U++);
990         v = *(V++);
991         uvRed = (V_RED_COEF*v) >> SHIFT;
992         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
993         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
994
995         tableY = table + *(Y++);
996         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
997                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
998                         uvGreen] |
999                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1000         *(dest++) = tmp24;
1001         *(dest++) = tmp24 >> 8;
1002         *(dest++) = tmp24 >> 16;
1003
1004         tableY = table + *(Y++);
1005         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1006                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1007                         uvGreen] |
1008                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1009         *(dest++) = tmp24;
1010         *(dest++) = tmp24 >> 8;
1011         *(dest++) = tmp24 >> 16;
1012     }
1013
1014     if (width & 1) {
1015         u = *(U++);
1016         v = *(V++);
1017         uvRed = (V_RED_COEF*v) >> SHIFT;
1018         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1019         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1020
1021         tableY = table + *(Y++);
1022         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1023                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1024                         uvGreen] |
1025                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1026         *(dest++) = tmp24;
1027         *(dest++) = tmp24 >> 8;
1028         *(dest++) = tmp24 >> 16;
1029     }
1030 }
1031
1032 static void yuvToRgb32 (unsigned char * Y,
1033                         unsigned char * U, unsigned char * V,
1034                         int * dest, int table[1935], int width)
1035 {
1036     int i;
1037     int u;
1038     int v;
1039     int uvRed;
1040     int uvGreen;
1041     int uvBlue;
1042     int * tableY;
1043
1044     i = width >> 4;
1045     while (i--) {
1046         u = *(U++);
1047         v = *(V++);
1048         uvRed = (V_RED_COEF*v) >> SHIFT;
1049         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1050         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1051
1052         tableY = table + *(Y++);
1053         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1054                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1055                             uvGreen] |
1056                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1057
1058         tableY = table + *(Y++);
1059         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1060                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1061                             uvGreen] |
1062                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1063
1064         u = *(U++);
1065         v = *(V++);
1066         uvRed = (V_RED_COEF*v) >> SHIFT;
1067         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1068         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1069
1070         tableY = table + *(Y++);
1071         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1072                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1073                             uvGreen] |
1074                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1075
1076         tableY = table + *(Y++);
1077         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1078                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1079                             uvGreen] |
1080                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1081
1082         u = *(U++);
1083         v = *(V++);
1084         uvRed = (V_RED_COEF*v) >> SHIFT;
1085         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1086         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1087
1088         tableY = table + *(Y++);
1089         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1090                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1091                             uvGreen] |
1092                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1093
1094         tableY = table + *(Y++);
1095         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1096                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1097                             uvGreen] |
1098                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1099
1100         u = *(U++);
1101         v = *(V++);
1102         uvRed = (V_RED_COEF*v) >> SHIFT;
1103         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1104         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1105
1106         tableY = table + *(Y++);
1107         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1108                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1109                             uvGreen] |
1110                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1111
1112         tableY = table + *(Y++);
1113         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1114                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1115                             uvGreen] |
1116                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1117
1118         u = *(U++);
1119         v = *(V++);
1120         uvRed = (V_RED_COEF*v) >> SHIFT;
1121         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1122         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1123
1124         tableY = table + *(Y++);
1125         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1126                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1127                             uvGreen] |
1128                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1129
1130         tableY = table + *(Y++);
1131         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1132                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1133                             uvGreen] |
1134                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1135
1136         u = *(U++);
1137         v = *(V++);
1138         uvRed = (V_RED_COEF*v) >> SHIFT;
1139         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1140         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1141
1142         tableY = table + *(Y++);
1143         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1144                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1145                             uvGreen] |
1146                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1147
1148         tableY = table + *(Y++);
1149         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1150                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1151                             uvGreen] |
1152                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1153
1154         u = *(U++);
1155         v = *(V++);
1156         uvRed = (V_RED_COEF*v) >> SHIFT;
1157         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1158         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1159
1160         tableY = table + *(Y++);
1161         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1162                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1163                             uvGreen] |
1164                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1165
1166         tableY = table + *(Y++);
1167         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1168                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1169                             uvGreen] |
1170                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1171
1172         u = *(U++);
1173         v = *(V++);
1174         uvRed = (V_RED_COEF*v) >> SHIFT;
1175         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1176         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1177
1178         tableY = table + *(Y++);
1179         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1180                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1181                             uvGreen] |
1182                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1183
1184         tableY = table + *(Y++);
1185         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1186                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1187                             uvGreen] |
1188                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1189     }
1190
1191     i = (width & 15) >> 1;
1192     while (i--) {
1193         u = *(U++);
1194         v = *(V++);
1195         uvRed = (V_RED_COEF*v) >> SHIFT;
1196         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1197         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1198
1199         tableY = table + *(Y++);
1200         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1201                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1202                             uvGreen] |
1203                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1204
1205         tableY = table + *(Y++);
1206         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1207                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1208                             uvGreen] |
1209                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1210     }
1211
1212     if (width & 1) {
1213         u = *(U++);
1214         v = *(V++);
1215         uvRed = (V_RED_COEF*v) >> SHIFT;
1216         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1217         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1218
1219         tableY = table + *(Y++);
1220         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1221                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1222                             uvGreen] |
1223                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1224     }
1225 }