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