]> git.sesse.net Git - vlc/blob - src/video_output/video_yuv.c
Changement de l'API de vout (chroma_width)
[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 <errno.h>
14 #include <math.h>
15 #include <string.h>
16 #include <stdlib.h>
17
18 #ifdef VIDEO_X11
19 #include <X11/Xlib.h>                           /* for video_sys.h in X11 mode */
20 #endif
21
22 #include "common.h"
23 #include "config.h"
24 #include "mtime.h"
25 #include "vlc_thread.h"
26 #include "video.h"
27 #include "video_output.h"
28 #include "intf_msg.h"
29
30 /*******************************************************************************
31  * Constants
32  *******************************************************************************/
33
34 /* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
35 const int MATRIX_COEFFICIENTS_TABLE[8][4] =
36 {
37   {117504, 138453, 13954, 34903},       /* no sequence_display_extension */
38   {117504, 138453, 13954, 34903},       /* ITU-R Rec. 709 (1990) */
39   {104597, 132201, 25675, 53279},       /* unspecified */
40   {104597, 132201, 25675, 53279},       /* reserved */
41   {104448, 132798, 24759, 53109},       /* FCC */
42   {104597, 132201, 25675, 53279},       /* ITU-R Rec. 624-4 System B, G */
43   {104597, 132201, 25675, 53279},       /* SMPTE 170M */
44   {117579, 136230, 16907, 35559}        /* SMPTE 240M (1987) */
45 };
46
47 /*******************************************************************************
48  * Local prototypes
49  *******************************************************************************/
50 static int      BinaryLog         ( u32 i );
51 static void     MaskToShift       ( int *pi_right, int *pi_left, u32 i_mask );
52 static void     SetTables         ( vout_thread_t *p_vout );
53
54 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,
55                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
56 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,
57                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
58 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,
59                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
60 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,
61                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
62 static void     ConvertYUV422RGB16( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
63                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
64 static void     ConvertYUV444RGB16( p_vout_thread_t p_vout, void *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_eol, int i_pic_eol, int i_scale );
66 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,
67                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
68 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,
69                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
70 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,
71                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
72 static void     ConvertYUV420RGB32( p_vout_thread_t p_vout, void *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_eol, int i_pic_eol, int i_scale );
74 static void     ConvertYUV422RGB32( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
75                                     int i_width, int i_height, int i_eol, int i_pic_eol, int i_scale );
76 static void     ConvertYUV444RGB32( 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_eol, int i_pic_eol, int i_scale );
78 static void     Scale16           ( p_vout_thread_t p_vout, void *p_pic, void *p_buffer, 
79                                     int i_width, int i_height, int i_eol, int i_pic_eol, float f_alpha, float f_beta );
80 static void     Scale24           ( p_vout_thread_t p_vout, void *p_pic, void *p_buffer, 
81                                     int i_width, int i_height, int i_eol, int i_pic_eol, float f_alpha, float f_beta );
82 static void     Scale32           ( p_vout_thread_t p_vout, void *p_pic, void *p_buffer, 
83                                     int i_width, int i_height, int i_eol, int i_pic_eol, float f_alpha, float f_beta );
84
85 /*******************************************************************************
86  * CLIP_BYTE macro: boundary detection
87  *******************************************************************************
88  * Return parameter if between 0 and 255, else return nearest boundary (0 or 
89  * 255). This macro is used to build translations tables.
90  *******************************************************************************/
91 #define CLIP_BYTE( i_val ) ( (i_val < 0) ? 0 : ((i_val > 255) ? 255 : i_val) )
92
93 /*******************************************************************************
94  * LINE_COPY macro: memcopy using 16 pixels blocks
95  *******************************************************************************
96  * Variables:
97  *      p_pic                   destination pointer
98  *      p_pic_src               source pointer
99  *      i_width                 width
100  *      i_x                     index
101  *******************************************************************************/
102 #define LINE_COPY                                                       \
103 for( i_x = 0; i_x < i_width; i_x+=16 )                                  \
104 {                                                                       \
105     *p_pic++ = *p_pic_src++;                                            \
106     *p_pic++ = *p_pic_src++;                                            \
107     *p_pic++ = *p_pic_src++;                                            \
108     *p_pic++ = *p_pic_src++;                                            \
109     *p_pic++ = *p_pic_src++;                                            \
110     *p_pic++ = *p_pic_src++;                                            \
111     *p_pic++ = *p_pic_src++;                                            \
112     *p_pic++ = *p_pic_src++;                                            \
113     *p_pic++ = *p_pic_src++;                                            \
114     *p_pic++ = *p_pic_src++;                                            \
115     *p_pic++ = *p_pic_src++;                                            \
116     *p_pic++ = *p_pic_src++;                                            \
117     *p_pic++ = *p_pic_src++;                                            \
118     *p_pic++ = *p_pic_src++;                                            \
119     *p_pic++ = *p_pic_src++;                                            \
120     *p_pic++ = *p_pic_src++;                                            \
121 }
122
123 /*******************************************************************************
124  * CONVERT_YUV_GRAY macro: grayscale YUV convertion
125  *******************************************************************************
126  * Variables:
127  *      ...see vout_convert_t
128  *      i_x, i_y                coordinates
129  *      i_pic_copy              same type as p_pic
130  *      p_gray                  gray translation table
131  *******************************************************************************/
132 #define CONVERT_YUV_GRAY                                                \
133 /* Set scale factor to be ignored if it is 0 */                         \
134 if( !i_scale )                                                          \
135 {                                                                       \
136     i_scale = i_height;                                                 \
137 }                                                                       \
138                                                                         \
139 /* Main loop */                                                         \
140 for (i_y = 0; i_y < i_height ; i_y++)                                   \
141 {                                                                       \
142     for (i_x = 0; i_x < i_width; i_x += 16)                             \
143     {                                                                   \
144         /* Convert 16 pixels (width is always multiple of 16 */         \
145         *p_pic++ = p_gray[ *p_y++ ];                                    \
146         *p_pic++ = p_gray[ *p_y++ ];                                    \
147         *p_pic++ = p_gray[ *p_y++ ];                                    \
148         *p_pic++ = p_gray[ *p_y++ ];                                    \
149         *p_pic++ = p_gray[ *p_y++ ];                                    \
150         *p_pic++ = p_gray[ *p_y++ ];                                    \
151         *p_pic++ = p_gray[ *p_y++ ];                                    \
152         *p_pic++ = p_gray[ *p_y++ ];                                    \
153         *p_pic++ = p_gray[ *p_y++ ];                                    \
154         *p_pic++ = p_gray[ *p_y++ ];                                    \
155         *p_pic++ = p_gray[ *p_y++ ];                                    \
156         *p_pic++ = p_gray[ *p_y++ ];                                    \
157         *p_pic++ = p_gray[ *p_y++ ];                                    \
158         *p_pic++ = p_gray[ *p_y++ ];                                    \
159         *p_pic++ = p_gray[ *p_y++ ];                                    \
160         *p_pic++ = p_gray[ *p_y++ ];                                    \
161     }                                                                   \
162                                                                         \
163     /* Handle scale factor */                                           \
164     if( ! (i_y % i_scale) )                                             \
165     {                                                                   \
166         if( i_scale < 0 )                                               \
167         {                                                               \
168             /* Copy previous line */                                    \
169             p_pic_src = p_pic - i_width;                                \
170             p_pic += i_pic_eol;                                         \
171             LINE_COPY                                                   \
172         }                                                               \
173         else                                                            \
174         {                                                               \
175             /* Ignore next line */                                      \
176             p_y += i_eol + i_width;                                     \
177             i_y++;                                                      \
178         }                                                               \
179     }                                                                   \
180                                                                         \
181     /* Skip until beginning of next line */                             \
182     p_pic += i_pic_eol;                                                 \
183     p_y   += i_eol;                                                     \
184 }
185
186 /*******************************************************************************
187  * CONVERT_YUV_RGB: color YUV convertion
188  *******************************************************************************
189  * Parameters
190  *      CHROMA                  420, 422 or 444
191  * Variables:
192  *      ...see vout_convert_t
193  *      i_x, i_y                coordinates
194  *      i_uval, i_yval, i_vval  samples
195  *      p_pic_src               same type as p_pic
196  *      i_chroma_width          chroma width
197  *      i_chroma_eol            chroma eol
198  *      p_red                   red translation table
199  *      p_green                 green translation table
200  *      p_blue                  blue translation table
201  *******************************************************************************/
202 #define CONVERT_YUV_RGB                                                 \
203 /* Set scale factor to be ignored if it is 0 */                         \
204 if( !i_scale )                                                          \
205 {                                                                       \
206     i_scale = i_height;                                                 \
207 }                                                                       \
208                                                                         \
209 /* Main loop */                                                         \
210 for (i_y = 0; i_y < i_height ; i_y++)                                   \
211 {                                                                       \
212     for (i_x=0; i_x < i_width; i_x += 2 )                               \
213     {                                                                   \
214         /* First sample (complete) */                                   \
215         i_yval = 76309 * *p_y++ - 1188177;                              \
216         i_uval = *p_u++ - 128;                                          \
217         i_vval = *p_v++ - 128;                                          \
218         *p_pic++ =                                                      \
219             p_red  [(i_yval+i_crv*i_vval)                >>16] |        \
220             p_green[(i_yval-i_cgu*i_uval-i_cgv*i_vval)   >>16] |        \
221             p_blue [(i_yval+i_cbu*i_uval)                >>16];         \
222         i_yval = 76309 * *p_y++ - 1188177;                              \
223         /* Second sample (partial) */                                   \
224         if( CHROMA == 444 )                                             \
225         {                                                               \
226             i_uval = *p_u++ - 128;                                      \
227             i_vval = *p_v++ - 128;                                      \
228         }                                                               \
229         *p_pic++ =                                                      \
230             p_red  [(i_yval+i_crv*i_vval)                >>16] |        \
231             p_green[(i_yval-i_cgu*i_uval-i_cgv*i_vval)   >>16] |        \
232             p_blue [(i_yval+i_cbu*i_uval)                >>16];         \
233     }                                                                   \
234                                                                         \
235     /* Handle scale factor */                                           \
236     if( ! (i_y % i_scale) )                                             \
237     {                                                                   \
238         if( i_scale < 0 )                                               \
239         {                                                               \
240             /* Copy previous line */                                    \
241             p_pic_src = p_pic - i_width;                                \
242             p_pic += i_pic_eol;                                         \
243             LINE_COPY                                                   \
244         }                                                               \
245         else                                                            \
246         {                                                               \
247             /* Ignore next line, rewind if in 4:2:0 */                  \
248             p_y += i_eol + i_width;                                     \
249             if( (CHROMA == 420) && !(i_y & 0x1) )                       \
250             {                                                           \
251                 p_u -= i_chroma_width;                                  \
252                 p_v -= i_chroma_width;                                  \
253             }                                                           \
254             else                                                        \
255             {                                                           \
256                 p_u += i_chroma_eol;                                    \
257                 p_v += i_chroma_eol;                                    \
258             }                                                           \
259             i_y++;                                                      \
260         }                                                               \
261     }                                                                   \
262                                                                         \
263     /* Rewind u and v values in 4:2:0, or skip until next line */       \
264     if( (CHROMA == 420) && !(i_y & 0x1) )                               \
265     {                                                                   \
266         p_u -= i_chroma_width;                                          \
267         p_v -= i_chroma_width;                                          \
268     }                                                                   \
269     else                                                                \
270     {                                                                   \
271         p_u += i_chroma_eol;                                            \
272         p_v += i_chroma_eol;                                            \
273     }                                                                   \
274                                                                         \
275     /* Skip until beginning of next line */                             \
276     p_pic += i_pic_eol;                                                 \
277     p_y   += i_eol;                                                     \
278 }
279
280 /*******************************************************************************
281  * vout_InitTables: allocate and initialize translations tables
282  *******************************************************************************
283  * This function will allocate memory to store translation tables, depending
284  * of the screen depth.
285  *******************************************************************************/
286 int vout_InitTables( vout_thread_t *p_vout )
287 {
288     /* Allocate memory and set pointers */
289     p_vout->tables.p_base = malloc( ( 3 * 1024 ) *   
290                                     ( p_vout->i_bytes_per_pixel != 3 ? 
291                                       p_vout->i_bytes_per_pixel : 4 ));
292     if( p_vout->tables.p_base == NULL )
293     {
294         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
295         return( 1 );                
296     }
297
298     /* Initialize tables */
299     SetTables( p_vout );    
300     return( 0 );    
301 }
302
303 /*******************************************************************************
304  * vout_ResetTables: re-initialize translations tables
305  *******************************************************************************
306  * This function will initialize the tables allocated by vout_CreateTables and
307  * set functions pointers.
308  *******************************************************************************/
309 int vout_ResetTables( vout_thread_t *p_vout )
310 {
311     // ?? realloc ?
312     SetTables( p_vout );
313     return( 0 );    
314 }
315
316 /*******************************************************************************
317  * vout_EndTables: destroy translations tables
318  *******************************************************************************
319  * Free memory allocated by vout_CreateTables.
320  *******************************************************************************/
321 void vout_EndTables( vout_thread_t *p_vout )
322 {
323     free( p_vout->tables.p_base );
324 }
325
326 /* following functions are local */
327
328 /*******************************************************************************
329  * BinaryLog: computes the base 2 log of a binary value
330  *******************************************************************************
331  * This functions is used by MaskToShift during tables initialisation, to
332  * get a bit index from a binary value.
333  *******************************************************************************/
334 static int BinaryLog(u32 i)
335 {
336     int i_log;
337
338     i_log = 0;
339     if (i & 0xffff0000) 
340     {        
341         i_log = 16;
342     }    
343     if (i & 0xff00ff00) 
344     {        
345         i_log += 8;
346     }    
347     if (i & 0xf0f0f0f0) 
348     {        
349         i_log += 4;
350     }    
351     if (i & 0xcccccccc) 
352     {        
353         i_log += 2;
354     }    
355     if (i & 0xaaaaaaaa) 
356     {        
357         i_log++;
358     }    
359     if (i != ((u32)1 << i_log))
360     {        
361         intf_ErrMsg("internal error: binary log overflow\n");        
362     }    
363
364     return( i_log );
365 }
366
367 /*******************************************************************************
368  * MaskToShift: Transform a color mask into right and left shifts
369  *******************************************************************************
370  * This function is used during table initialisation. It can return a value
371  *******************************************************************************/
372 static void MaskToShift (int *pi_right, int *pi_left, u32 i_mask)
373 {
374     u32 i_low, i_high;                   /* lower hand higher bits of the mask */
375
376     /* Get bits */
377     i_low =  i_mask & (- i_mask);                     /* lower bit of the mask */
378     i_high = i_mask + i_low;                         /* higher bit of the mask */
379
380     /* Transform bits into an index */
381     i_low =  BinaryLog (i_low);
382     i_high = BinaryLog (i_high);
383
384     /* Update pointers and return */
385     *pi_left =   i_low;
386     *pi_right = (8 - i_high + i_low);
387 }
388
389 /*******************************************************************************
390  * SetTables: compute tables and set function pointers
391  *******************************************************************************/
392 static void SetTables( vout_thread_t *p_vout )
393 {
394     u8          i_gamma[256];                                   /* gamma table */    
395     int         i_index;                                    /* index in tables */
396     int         i_red_right, i_red_left;                         /* red shifts */
397     int         i_green_right, i_green_left;                   /* green shifts */
398     int         i_blue_right, i_blue_left;                      /* blue shifts */
399
400     /*
401      * Build gamma table 
402      */     
403     for( i_index = 0; i_index < 256; i_index++ )
404     {
405         i_gamma[i_index] = 255. * pow( (double)i_index / 255., p_vout->f_gamma );        
406     }
407
408     /*          
409      * Set color masks and shifts
410      */
411     switch( p_vout->i_screen_depth )
412     {
413     case 15:
414         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
415         MaskToShift( &i_green_right, &i_green_left, 0x03e0 );
416         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );        
417         break;        
418     case 16:
419         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
420         MaskToShift( &i_green_right, &i_green_left, 0x07e0 );
421         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );
422         break;        
423     case 24:
424     case 32:        
425         MaskToShift( &i_red_right,   &i_red_left,   0x00ff0000 );
426         MaskToShift( &i_green_right, &i_green_left, 0x0000ff00 );
427         MaskToShift( &i_blue_right,  &i_blue_left,  0x000000ff );
428         break;
429 #ifdef DEBUG
430     default:
431         intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
432         break;        
433 #endif      
434     }
435
436     /*
437      * Set pointers and build YUV tables
438      */        
439     if( p_vout->b_grayscale )
440     {
441         /* Grayscale: build gray table */
442         switch( p_vout->i_screen_depth )
443         {
444         case 15:
445         case 16:         
446             p_vout->tables.yuv.gray16.p_gray =  (u16 *)p_vout->tables.p_base + 384;
447             for( i_index = -384; i_index < 640; i_index++) 
448             {
449                 p_vout->tables.yuv.gray16.p_gray[ i_index ] = 
450                     ((i_gamma[CLIP_BYTE( i_index )] >> i_red_right)   << i_red_left)   |
451                     ((i_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) |
452                     ((i_gamma[CLIP_BYTE( i_index )] >> i_blue_right)  << i_blue_left);                
453             }
454             break;        
455         case 24:
456         case 32:        
457             p_vout->tables.yuv.gray32.p_gray =  (u32 *)p_vout->tables.p_base + 384;
458             for( i_index = -384; i_index < 640; i_index++) 
459             {
460                 p_vout->tables.yuv.gray32.p_gray[ i_index ] = 
461                     ((i_gamma[CLIP_BYTE( i_index )] >> i_red_right)   << i_red_left)   |
462                     ((i_gamma[CLIP_BYTE( i_index )] >> i_green_right) << i_green_left) |
463                     ((i_gamma[CLIP_BYTE( i_index )] >> i_blue_right)  << i_blue_left);                
464             }        
465             break;        
466         }
467     }
468     else
469     {
470         /* Color: build red, green and blue tables */
471         switch( p_vout->i_screen_depth )
472         {
473         case 15:
474         case 16:            
475             p_vout->tables.yuv.rgb16.p_red =    (u16 *)p_vout->tables.p_base +          384;
476             p_vout->tables.yuv.rgb16.p_green =  (u16 *)p_vout->tables.p_base +   1024 + 384;
477             p_vout->tables.yuv.rgb16.p_blue =   (u16 *)p_vout->tables.p_base + 2*1024 + 384;
478             for( i_index = -384; i_index < 640; i_index++) 
479             {
480                 p_vout->tables.yuv.rgb16.p_red[i_index] =   (i_gamma[CLIP_BYTE(i_index)]>>i_red_right)<<i_red_left;
481                 p_vout->tables.yuv.rgb16.p_green[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_green_right)<<i_green_left;
482                 p_vout->tables.yuv.rgb16.p_blue[i_index] =  (i_gamma[CLIP_BYTE(i_index)]>>i_blue_right)<<i_blue_left;
483             }
484             break;        
485         case 24:
486         case 32:
487             p_vout->tables.yuv.rgb32.p_red =    (u32 *)p_vout->tables.p_base +          384;
488             p_vout->tables.yuv.rgb32.p_green =  (u32 *)p_vout->tables.p_base +   1024 + 384;
489             p_vout->tables.yuv.rgb32.p_blue =   (u32 *)p_vout->tables.p_base + 2*1024 + 384;
490             for( i_index = -384; i_index < 640; i_index++) 
491             {
492                 p_vout->tables.yuv.rgb32.p_red[i_index] =   (i_gamma[CLIP_BYTE(i_index)]>>i_red_right)<<i_red_left;
493                 p_vout->tables.yuv.rgb32.p_green[i_index] = (i_gamma[CLIP_BYTE(i_index)]>>i_green_right)<<i_green_left;
494                 p_vout->tables.yuv.rgb32.p_blue[i_index] =  (i_gamma[CLIP_BYTE(i_index)]>>i_blue_right)<<i_blue_left;
495             }
496             break;        
497         }
498     }    
499     
500     /*
501      * Set functions pointers
502      */
503     if( p_vout->b_grayscale )
504     {
505         /* Grayscale */
506         switch( p_vout->i_screen_depth )
507         {
508         case 15:
509         case 16:  
510             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray16;        
511             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray16;        
512             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray16;        
513             p_vout->p_Scale =           (vout_scale_t *) Scale16;                    
514             break;        
515         case 24:
516             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray24;        
517             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray24;        
518             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray24;        
519             p_vout->p_Scale =           (vout_scale_t *) Scale24;
520             break;        
521         case 32:        
522             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray32;        
523             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray32;        
524             p_vout->p_ConvertYUV420 = (vout_convert_t *) ConvertY4Gray32;        
525             p_vout->p_Scale =           (vout_scale_t *) Scale32;                    
526             break;        
527         }        
528     }
529     else
530     {
531         /* Color */
532         switch( p_vout->i_screen_depth )
533         {
534         case 15:
535         case 16:  
536             p_vout->p_ConvertYUV420 =   (vout_convert_t *) ConvertYUV420RGB16;        
537             p_vout->p_ConvertYUV422 =   (vout_convert_t *) ConvertYUV422RGB16;        
538             p_vout->p_ConvertYUV444 =   (vout_convert_t *) ConvertYUV444RGB16;        
539             p_vout->p_Scale =           (vout_scale_t *)   Scale16;                    
540             break;        
541         case 24:
542             p_vout->p_ConvertYUV420 =   (vout_convert_t *) ConvertYUV420RGB24;        
543             p_vout->p_ConvertYUV422 =   (vout_convert_t *) ConvertYUV422RGB24;        
544             p_vout->p_ConvertYUV444 =   (vout_convert_t *) ConvertYUV444RGB24;        
545             p_vout->p_Scale =           (vout_scale_t *)   Scale24;                    
546             break;        
547         case 32:        
548             p_vout->p_ConvertYUV420 =   (vout_convert_t *) ConvertYUV420RGB32;        
549             p_vout->p_ConvertYUV422 =   (vout_convert_t *) ConvertYUV422RGB32;        
550             p_vout->p_ConvertYUV444 =   (vout_convert_t *) ConvertYUV444RGB32;        
551             p_vout->p_Scale =           (vout_scale_t *)   Scale32;                    
552             break;        
553         }
554     }        
555 }
556
557 /*******************************************************************************
558  * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 15 or 16 bpp
559  *******************************************************************************/
560 static void ConvertY4Gray16( p_vout_thread_t p_vout, u16 *p_pic,
561                              yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
562                              int i_width, int i_height, int i_eol, int i_pic_eol,
563                              int i_scale )
564 {
565     u16 *       p_pic_src;                   /* source pointer in case of copy */
566     u16 *       p_gray;                                          /* gray table */    
567     int         i_x, i_y;                               /* picture coordinates */
568     
569     p_gray = p_vout->tables.yuv.gray16.p_gray;
570     CONVERT_YUV_GRAY
571 }
572
573 /*******************************************************************************
574  * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 24 bpp
575  *******************************************************************************/
576 static void ConvertY4Gray24( p_vout_thread_t p_vout, void *p_pic,
577                              yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
578                              int i_width, int i_height, int i_eol, int i_pic_eol,
579                              int i_scale )
580 {
581     //??
582 }
583
584 /*******************************************************************************
585  * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 32 bpp
586  *******************************************************************************/
587 static void ConvertY4Gray32( p_vout_thread_t p_vout, u32 *p_pic,
588                              yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
589                              int i_width, int i_height, int i_eol, int i_pic_eol,
590                              int i_scale )
591 {
592     u32 *       p_pic_src;                   /* source pointer in case of copy */
593     u32 *       p_gray;                                          /* gray table */    
594     int         i_x, i_y;                               /* picture coordinates */
595     
596     p_gray = p_vout->tables.yuv.gray32.p_gray;
597     CONVERT_YUV_GRAY
598 }
599
600 /*******************************************************************************
601  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 15 or 16 bpp
602  *******************************************************************************/
603 static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic,
604                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
605                                 int i_width, int i_height, int i_eol, int i_pic_eol,
606                                 int i_scale )
607 {
608     u16 *       p_pic_src;                   /* source pointer in case of copy */
609     u16 *       p_red;                                            /* red table */
610     u16 *       p_green;                                        /* green table */
611     u16 *       p_blue;                                          /* blue table */
612     int         i_uval, i_yval, i_vval;                             /* samples */   
613     int         i_x, i_y;                               /* picture coordinates */
614     int         i_chroma_width, i_chroma_eol;      /* width and eol for chroma */
615     int         i_crv;
616     
617 /*    p_red   = p_vout->tables.yuv.rgb16.p_red;
618     p_green = p_vout->tables.yuv.rgb16.p_green;
619     p_blue  = p_vout->tables.yuv.rgb16.p_blue;
620     i_chroma_width =    i_width / 4;
621     i_chroma_eol =      i_eol / 4;
622     CONVERT_YUV_RGB*/
623 }
624
625 /*******************************************************************************
626  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 15 or 16 bpp
627  *******************************************************************************/
628 static void ConvertYUV422RGB16( p_vout_thread_t p_vout, void *p_pic,
629                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
630                                 int i_width, int i_height, int i_eol, int i_pic_eol,
631                                 int i_scale )
632 {
633     //??
634 }
635
636 /*******************************************************************************
637  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 15 or 16 bpp
638  *******************************************************************************/
639 static void ConvertYUV444RGB16( p_vout_thread_t p_vout, void *p_pic,
640                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
641                                 int i_width, int i_height, int i_eol, int i_pic_eol,
642                                 int i_scale )
643 {
644     //??
645 }
646
647 /*******************************************************************************
648  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 24 bpp
649  *******************************************************************************/
650 static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic,
651                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
652                                 int i_width, int i_height, int i_eol, int i_pic_eol,
653                                 int i_scale )
654 {
655     //???
656 }
657
658 /*******************************************************************************
659  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 24 bpp
660  *******************************************************************************/
661 static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic,
662                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
663                                 int i_width, int i_height, int i_eol, int i_pic_eol,
664                                 int i_scale )
665 {
666     //???
667 }
668
669 /*******************************************************************************
670  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 24 bpp
671  *******************************************************************************/
672 static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic,
673                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
674                                 int i_width, int i_height, int i_eol, int i_pic_eol,
675                                 int i_scale )
676 {    
677     //???
678 }
679
680 /*******************************************************************************
681  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 32 bpp
682  *******************************************************************************/
683 static void ConvertYUV420RGB32( p_vout_thread_t p_vout, void *p_pic,
684                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
685                                 int i_width, int i_height, int i_eol, int i_pic_eol,
686                                 int i_scale )
687 {
688     //???
689 }
690
691 /*******************************************************************************
692  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 32 bpp
693  *******************************************************************************/
694 static void ConvertYUV422RGB32( p_vout_thread_t p_vout, void *p_pic,
695                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
696                                 int i_width, int i_height, int i_eol, int i_pic_eol,
697                                 int i_scale )
698 {
699     //???
700 }
701
702 /*******************************************************************************
703  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 32 bpp
704  *******************************************************************************/
705 static void ConvertYUV444RGB32( p_vout_thread_t p_vout, void *p_pic,
706                                 yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
707                                 int i_width, int i_height, int i_eol, int i_pic_eol,
708                                 int i_scale )
709 {
710     //???
711 }
712
713 /*******************************************************************************
714  * Scale16: 15 or 16 bpp picture scaling
715  *******************************************************************************/
716 static void Scale16( p_vout_thread_t p_vout, void *p_pic, void *p_buffer, 
717                      int i_width, int i_height, int i_eol, int i_pic_eol, float f_alpha, float f_beta )
718 {
719     //???
720 }
721
722 /*******************************************************************************
723  * Scale24: 24 bpp picture scaling
724  *******************************************************************************/
725 static void Scale24( p_vout_thread_t p_vout, void *p_pic, void *p_buffer, 
726                      int i_width, int i_height, int i_eol, int i_pic_eol, float f_alpha, float f_beta )
727 {
728     //???
729 }
730
731 /*******************************************************************************
732  * Scale32: 32 bpp picture scaling
733  *******************************************************************************/
734 static void Scale32( p_vout_thread_t p_vout, void *p_pic, void *p_buffer, 
735                      int i_width, int i_height, int i_eol, int i_pic_eol, float f_alpha, float f_beta )
736 {
737     //???
738 }
739
740 //-------------------------
741
742 /*******************************************************************************
743  * External prototypes
744  *******************************************************************************/
745 #ifdef HAVE_MMX
746 /* YUV transformations for MMX - in video_yuv_mmx.S 
747  *      p_y, p_u, p_v:          Y U and V planes
748  *      i_width, i_height:      frames dimensions (pixels)
749  *      i_ypitch, i_vpitch:     Y and V lines sizes (bytes)
750  *      i_aspect:               vertical aspect factor
751  *      p_pic:                  RGB frame
752  *      i_dci_offset:           ?? x offset for left image border
753  *      i_offset_to_line_0:     ?? x offset for left image border
754  *      i_pitch:                RGB line size (bytes)
755  *      i_colortype:            0 for 565, 1 for 555 */
756 static YUV420_16_MMX( u8* p_y, u8* p_u, u8 *p_v, 
757                          unsigned int i_width, unsigned int i_height,
758                          unsigned int i_ypitch, unsigned int i_vpitch,
759                          unsigned int i_aspect, u8 *p_pic, 
760                          u32 i_dci_offset, u32 i_offset_to_line_0,
761                          int CCOPitch, int i_colortype );
762 #endif
763
764 //-------------------- walken code follow --------------------------------
765
766
767
768
769 /*
770  * YUV to RGB routines.
771  *
772  * these routines calculate r, g and b values from each pixel's y, u and v.
773  * these r, g an b values are then passed thru a table lookup to take the
774  * gamma curve into account and find the corresponding pixel value.
775  *
776  * the table must store more than 3*256 values because of the possibility
777  * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
778  * values are in the following intervals :
779  * -176 to 255+176 for red
780  * -133 to 255+133 for green
781  * -222 to 255+222 for blue
782  *
783  * If the input y,u,v values are right, the r,g,b results are not expected
784  * to move out of the 0 to 255 interval but who knows what will happen in
785  * real use...
786  *
787  * the red, green and blue conversion tables are stored in a single 1935-entry
788  * array. The respective positions of each component in the array have been
789  * calculated to minimize the cache interactions of the 3 tables.
790  */
791
792 int rgbTable16 (short table [1935],
793                        int redMask, int greenMask, int blueMask,
794                        unsigned char gamma[256])
795 {
796     int redRight;
797     int redLeft;
798     int greenRight;
799     int greenLeft;
800     int blueRight;
801     int blueLeft;
802     short * redTable;
803     short * greenTable;
804     short * blueTable;
805     int i;
806     int y;
807
808     MaskToShift (&redRight, &redLeft, redMask);    
809     MaskToShift (&greenRight, &greenLeft, greenMask);    
810     MaskToShift (&blueRight, &blueLeft, blueMask);
811
812     /*
813      * green blue red +- 2 just to be sure
814      * green = 0-525 [151-370]
815      * blue = 594-1297 [834-1053] <834-29>
816      * red = 1323-1934 [1517-1736] <493-712>
817      */
818
819     redTable = table + 1501;
820     greenTable = table + 135;
821     blueTable = table + 818;
822
823     for (i = 0; i < 178; i++) {
824         redTable[i-178] = 0;
825         redTable[i+256] = redMask;
826     }
827     for (i = 0; i < 135; i++) {
828         greenTable[i-135] = 0;
829         greenTable[i+256] = greenMask;
830     }
831     for (i = 0; i < 224; i++) {
832         blueTable[i-224] = 0;
833         blueTable[i+256] = blueMask;
834     }
835
836     for (i = 0; i < 256; i++) {
837         y = gamma[i];
838         redTable[i] = ((y >> redRight) << redLeft);
839         greenTable[i] = ((y >> greenRight) << greenLeft);
840         blueTable[i] = ((y >> blueRight) << blueLeft);
841     }
842
843     return 0;
844 }
845
846 static int rgbTable32 (int table [1935],
847                        int redMask, int greenMask, int blueMask,
848                        unsigned char gamma[256])
849 {
850     int redRight;
851     int redLeft;
852     int greenRight;
853     int greenLeft;
854     int blueRight;
855     int blueLeft;
856     int * redTable;
857     int * greenTable;
858     int * blueTable;
859     int i;
860     int y;
861
862     MaskToShift (&redRight, &redLeft, redMask);
863     MaskToShift (&greenRight, &greenLeft, greenMask);
864     MaskToShift (&blueRight, &blueLeft, blueMask);
865     
866
867     /*
868      * green blue red +- 2 just to be sure
869      * green = 0-525 [151-370]
870      * blue = 594-1297 [834-1053] <834-29>
871      * red = 1323-1934 [1517-1736] <493-712>
872      */
873
874     redTable = table + 1501;
875     greenTable = table + 135;
876     blueTable = table + 818;
877
878     for (i = 0; i < 178; i++) {
879         redTable[i-178] = 0;
880         redTable[i+256] = redMask;
881     }
882     for (i = 0; i < 135; i++) {
883         greenTable[i-135] = 0;
884         greenTable[i+256] = greenMask;
885     }
886     for (i = 0; i < 224; i++) {
887         blueTable[i-224] = 0;
888         blueTable[i+256] = blueMask;
889     }
890
891     for (i = 0; i < 256; i++) {
892         y = gamma[i];
893         redTable[i] = ((y >> redRight) << redLeft);
894         greenTable[i] = ((y >> greenRight) << greenLeft);
895         blueTable[i] = ((y >> blueRight) << blueLeft);
896     }
897
898     return 0;
899 }
900
901 #define SHIFT 20
902 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
903 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
904 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
905 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
906
907  void yuvToRgb16 (unsigned char * Y,
908                         unsigned char * U, unsigned char * V,
909                         short * dest, short table[1935], int width)
910 {
911     int i;
912     int u;
913     int v;
914     int uvRed;
915     int uvGreen;
916     int uvBlue;
917     short * tableY;
918
919     i = width >> 4;
920     while (i--) {
921         u = *(U++);
922         v = *(V++);
923         uvRed = (V_RED_COEF*v) >> SHIFT;
924         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
925         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
926
927         tableY = table + *(Y++);
928         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
929                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
930                             uvGreen] |
931                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
932
933         tableY = table + *(Y++);
934         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
935                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
936                             uvGreen] |
937                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
938
939         u = *(U++);
940         v = *(V++);
941         uvRed = (V_RED_COEF*v) >> SHIFT;
942         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
943         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
944
945         tableY = table + *(Y++);
946         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
947                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
948                             uvGreen] |
949                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
950
951         tableY = table + *(Y++);
952         *(dest++) = (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
957         u = *(U++);
958         v = *(V++);
959         uvRed = (V_RED_COEF*v) >> SHIFT;
960         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
961         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
962
963         tableY = table + *(Y++);
964         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
965                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
966                             uvGreen] |
967                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
968
969         tableY = table + *(Y++);
970         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
971                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
972                             uvGreen] |
973                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
974
975         u = *(U++);
976         v = *(V++);
977         uvRed = (V_RED_COEF*v) >> SHIFT;
978         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
979         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
980
981         tableY = table + *(Y++);
982         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
983                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
984                             uvGreen] |
985                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
986
987         tableY = table + *(Y++);
988         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
989                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
990                             uvGreen] |
991                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
992
993         u = *(U++);
994         v = *(V++);
995         uvRed = (V_RED_COEF*v) >> SHIFT;
996         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
997         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
998
999         tableY = table + *(Y++);
1000         *(dest++) = (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
1005         tableY = table + *(Y++);
1006         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1007                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1008                             uvGreen] |
1009                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1010
1011         u = *(U++);
1012         v = *(V++);
1013         uvRed = (V_RED_COEF*v) >> SHIFT;
1014         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1015         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1016
1017         tableY = table + *(Y++);
1018         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1019                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1020                             uvGreen] |
1021                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1022
1023         tableY = table + *(Y++);
1024         *(dest++) = (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
1029         u = *(U++);
1030         v = *(V++);
1031         uvRed = (V_RED_COEF*v) >> SHIFT;
1032         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1033         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1034
1035         tableY = table + *(Y++);
1036         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1037                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1038                             uvGreen] |
1039                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1040
1041         tableY = table + *(Y++);
1042         *(dest++) = (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
1047         u = *(U++);
1048         v = *(V++);
1049         uvRed = (V_RED_COEF*v) >> SHIFT;
1050         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1051         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1052
1053         tableY = table + *(Y++);
1054         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1055                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1056                             uvGreen] |
1057                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1058
1059         tableY = table + *(Y++);
1060         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1061                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1062                             uvGreen] |
1063                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1064     }
1065
1066     i = (width & 15) >> 1;
1067     while (i--) {
1068         u = *(U++);
1069         v = *(V++);
1070         uvRed = (V_RED_COEF*v) >> SHIFT;
1071         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1072         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1073
1074         tableY = table + *(Y++);
1075         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1076                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1077                             uvGreen] |
1078                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1079
1080         tableY = table + *(Y++);
1081         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1082                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1083                             uvGreen] |
1084                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1085     }
1086
1087     if (width & 1) {
1088         u = *(U++);
1089         v = *(V++);
1090         uvRed = (V_RED_COEF*v) >> SHIFT;
1091         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1092         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
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 }
1101
1102 static void yuvToRgb24 (unsigned char * Y,
1103                         unsigned char * U, unsigned char * V,
1104                         char * dest, int table[1935], int width)
1105 {
1106     int i;
1107     int u;
1108     int v;
1109     int uvRed;
1110     int uvGreen;
1111     int uvBlue;
1112     int * tableY;
1113     int tmp24;
1114
1115     i = width >> 3;
1116     while (i--) {
1117         u = *(U++);
1118         v = *(V++);
1119         uvRed = (V_RED_COEF*v) >> SHIFT;
1120         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1121         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1122
1123         tableY = table + *(Y++);
1124         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1125                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1126                         uvGreen] |
1127                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1128         *(dest++) = tmp24;
1129         *(dest++) = tmp24 >> 8;
1130         *(dest++) = tmp24 >> 16;
1131
1132         tableY = table + *(Y++);
1133         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1134                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1135                         uvGreen] |
1136                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1137         *(dest++) = tmp24;
1138         *(dest++) = tmp24 >> 8;
1139         *(dest++) = tmp24 >> 16;
1140
1141         u = *(U++);
1142         v = *(V++);
1143         uvRed = (V_RED_COEF*v) >> SHIFT;
1144         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1145         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1146
1147         tableY = table + *(Y++);
1148         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1149                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1150                         uvGreen] |
1151                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1152         *(dest++) = tmp24;
1153         *(dest++) = tmp24 >> 8;
1154         *(dest++) = tmp24 >> 16;
1155
1156         tableY = table + *(Y++);
1157         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1158                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1159                         uvGreen] |
1160                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1161         *(dest++) = tmp24;
1162         *(dest++) = tmp24 >> 8;
1163         *(dest++) = tmp24 >> 16;
1164
1165         u = *(U++);
1166         v = *(V++);
1167         uvRed = (V_RED_COEF*v) >> SHIFT;
1168         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1169         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1170
1171         tableY = table + *(Y++);
1172         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1173                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1174                         uvGreen] |
1175                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1176         *(dest++) = tmp24;
1177         *(dest++) = tmp24 >> 8;
1178         *(dest++) = tmp24 >> 16;
1179
1180         tableY = table + *(Y++);
1181         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1182                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1183                         uvGreen] |
1184                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1185         *(dest++) = tmp24;
1186         *(dest++) = tmp24 >> 8;
1187         *(dest++) = tmp24 >> 16;
1188
1189         u = *(U++);
1190         v = *(V++);
1191         uvRed = (V_RED_COEF*v) >> SHIFT;
1192         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1193         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1194
1195         tableY = table + *(Y++);
1196         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1197                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1198                         uvGreen] |
1199                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1200         *(dest++) = tmp24;
1201         *(dest++) = tmp24 >> 8;
1202         *(dest++) = tmp24 >> 16;
1203
1204         tableY = table + *(Y++);
1205         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1206                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1207                         uvGreen] |
1208                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1209         *(dest++) = tmp24;
1210         *(dest++) = tmp24 >> 8;
1211         *(dest++) = tmp24 >> 16;
1212     }
1213
1214     i = (width & 7) >> 1;
1215     while (i--) {
1216         u = *(U++);
1217         v = *(V++);
1218         uvRed = (V_RED_COEF*v) >> SHIFT;
1219         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1220         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1221
1222         tableY = table + *(Y++);
1223         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1224                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1225                         uvGreen] |
1226                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1227         *(dest++) = tmp24;
1228         *(dest++) = tmp24 >> 8;
1229         *(dest++) = tmp24 >> 16;
1230
1231         tableY = table + *(Y++);
1232         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1233                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1234                         uvGreen] |
1235                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1236         *(dest++) = tmp24;
1237         *(dest++) = tmp24 >> 8;
1238         *(dest++) = tmp24 >> 16;
1239     }
1240
1241     if (width & 1) {
1242         u = *(U++);
1243         v = *(V++);
1244         uvRed = (V_RED_COEF*v) >> SHIFT;
1245         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1246         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1247
1248         tableY = table + *(Y++);
1249         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1250                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1251                         uvGreen] |
1252                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1253         *(dest++) = tmp24;
1254         *(dest++) = tmp24 >> 8;
1255         *(dest++) = tmp24 >> 16;
1256     }
1257 }
1258
1259 static void yuvToRgb32 (unsigned char * Y,
1260                         unsigned char * U, unsigned char * V,
1261                         int * dest, int table[1935], int width)
1262 {
1263     int i;
1264     int u;
1265     int v;
1266     int uvRed;
1267     int uvGreen;
1268     int uvBlue;
1269     int * tableY;
1270
1271     i = width >> 4;
1272     while (i--) {
1273         u = *(U++);
1274         v = *(V++);
1275         uvRed = (V_RED_COEF*v) >> SHIFT;
1276         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1277         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1278
1279         tableY = table + *(Y++);
1280         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1281                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1282                             uvGreen] |
1283                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1284
1285         tableY = table + *(Y++);
1286         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1287                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1288                             uvGreen] |
1289                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1290
1291         u = *(U++);
1292         v = *(V++);
1293         uvRed = (V_RED_COEF*v) >> SHIFT;
1294         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1295         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1296
1297         tableY = table + *(Y++);
1298         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1299                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1300                             uvGreen] |
1301                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1302
1303         tableY = table + *(Y++);
1304         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1305                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1306                             uvGreen] |
1307                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1308
1309         u = *(U++);
1310         v = *(V++);
1311         uvRed = (V_RED_COEF*v) >> SHIFT;
1312         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1313         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1314
1315         tableY = table + *(Y++);
1316         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1317                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1318                             uvGreen] |
1319                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1320
1321         tableY = table + *(Y++);
1322         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1323                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1324                             uvGreen] |
1325                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1326
1327         u = *(U++);
1328         v = *(V++);
1329         uvRed = (V_RED_COEF*v) >> SHIFT;
1330         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1331         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1332
1333         tableY = table + *(Y++);
1334         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1335                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1336                             uvGreen] |
1337                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1338
1339         tableY = table + *(Y++);
1340         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1341                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1342                             uvGreen] |
1343                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1344
1345         u = *(U++);
1346         v = *(V++);
1347         uvRed = (V_RED_COEF*v) >> SHIFT;
1348         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1349         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1350
1351         tableY = table + *(Y++);
1352         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1353                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1354                             uvGreen] |
1355                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1356
1357         tableY = table + *(Y++);
1358         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1359                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1360                             uvGreen] |
1361                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1362
1363         u = *(U++);
1364         v = *(V++);
1365         uvRed = (V_RED_COEF*v) >> SHIFT;
1366         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1367         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1368
1369         tableY = table + *(Y++);
1370         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1371                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1372                             uvGreen] |
1373                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1374
1375         tableY = table + *(Y++);
1376         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1377                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1378                             uvGreen] |
1379                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1380
1381         u = *(U++);
1382         v = *(V++);
1383         uvRed = (V_RED_COEF*v) >> SHIFT;
1384         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1385         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1386
1387         tableY = table + *(Y++);
1388         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1389                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1390                             uvGreen] |
1391                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1392
1393         tableY = table + *(Y++);
1394         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1395                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1396                             uvGreen] |
1397                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1398
1399         u = *(U++);
1400         v = *(V++);
1401         uvRed = (V_RED_COEF*v) >> SHIFT;
1402         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1403         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1404
1405         tableY = table + *(Y++);
1406         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1407                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1408                             uvGreen] |
1409                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1410
1411         tableY = table + *(Y++);
1412         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1413                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1414                             uvGreen] |
1415                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1416     }
1417
1418     i = (width & 15) >> 1;
1419     while (i--) {
1420         u = *(U++);
1421         v = *(V++);
1422         uvRed = (V_RED_COEF*v) >> SHIFT;
1423         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1424         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1425
1426         tableY = table + *(Y++);
1427         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1428                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1429                             uvGreen] |
1430                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1431
1432         tableY = table + *(Y++);
1433         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1434                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1435                             uvGreen] |
1436                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1437     }
1438
1439     if (width & 1) {
1440         u = *(U++);
1441         v = *(V++);
1442         uvRed = (V_RED_COEF*v) >> SHIFT;
1443         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1444         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1445
1446         tableY = table + *(Y++);
1447         *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1448                      tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1449                             uvGreen] |
1450                      tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1451     }
1452 }
1453
1454 /* API routines */
1455