]> git.sesse.net Git - vlc/blob - src/video_output/video_yuv.c
. prototypes de fonctions pour le 8bpp
[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 //?? no more used ?
33 const int MATRIX_COEFFICIENTS_TABLE[8][4] =
34 {
35   {117504, 138453, 13954, 34903},       /* no sequence_display_extension */
36   {117504, 138453, 13954, 34903},       /* ITU-R Rec. 709 (1990) */
37   {104597, 132201, 25675, 53279},       /* unspecified */
38   {104597, 132201, 25675, 53279},       /* reserved */
39   {104448, 132798, 24759, 53109},       /* FCC */
40   {104597, 132201, 25675, 53279},       /* ITU-R Rec. 624-4 System B, G */
41   {104597, 132201, 25675, 53279},       /* SMPTE 170M */
42   {117579, 136230, 16907, 35559}        /* SMPTE 240M (1987) */
43 };
44
45 /* Margins and offsets in convertion tables - Margins are used in case a RGB
46  * RGB convertion would give a value outside the 0-255 range. Offsets have been
47  * calculated to avoid using the same cache line for 2 tables. Convertion tables
48  * are 2*MARGIN + 256 long and stores pixels.*/
49 #define RED_MARGIN      178
50 #define GREEN_MARGIN    135
51 #define BLUE_MARGIN     224
52 #define RED_OFFSET      1501                                   /* 1323 to 1935 */
53 #define GREEN_OFFSET    135                                        /* 0 to 526 */
54 #define BLUE_OFFSET     818                                     /* 594 to 1298 */
55 #define RGB_TABLE_SIZE  1935                               /* total table size */
56
57 #define GRAY_MARGIN     384
58 #define GRAY_TABLE_SIZE 1024                               /* total table size */
59
60 //??
61 #define SHIFT 20
62 #define U_GREEN_COEF    ((int)(-0.391 * (1<<SHIFT) / 1.164))
63 #define U_BLUE_COEF     ((int)(2.018 * (1<<SHIFT) / 1.164))
64 #define V_RED_COEF      ((int)(1.596 * (1<<SHIFT) / 1.164))
65 #define V_GREEN_COEF    ((int)(-0.813 * (1<<SHIFT) / 1.164))
66
67 /*******************************************************************************
68  * Local prototypes
69  *******************************************************************************/
70 static int      BinaryLog         ( u32 i );
71 static void     MaskToShift       ( int *pi_right, int *pi_left, u32 i_mask );
72 static void     SetGammaTable     ( int *pi_table, double f_gamma );
73 static void     SetYUV            ( vout_thread_t *p_vout );
74 static void     SetOffset         ( int i_width, int i_height, int i_pic_width, int i_pic_height, 
75                                     boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
76
77 static void     ConvertY4Gray8    ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
78                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
79                                     int i_matrix_coefficients );
80 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,
81                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
82                                     int i_matrix_coefficients );
83 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,
84                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
85                                     int i_matrix_coefficients );
86 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,
87                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
88                                     int i_matrix_coefficients );
89 static void     ConvertYUV420RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
90                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
91                                     int i_matrix_coefficients );
92 static void     ConvertYUV422RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
93                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
94                                     int i_matrix_coefficients );
95 static void     ConvertYUV444RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
96                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
97                                     int i_matrix_coefficients );
98 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,
99                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
100                                     int i_matrix_coefficients );
101 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,
102                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
103                                     int i_matrix_coefficients );
104 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,
105                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
106                                     int i_matrix_coefficients );
107 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,
108                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
109                                     int i_matrix_coefficients );
110 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,
111                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
112                                     int i_matrix_coefficients );
113 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,
114                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
115                                     int i_matrix_coefficients );
116 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,
117                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
118                                     int i_matrix_coefficients );
119 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,
120                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
121                                     int i_matrix_coefficients );
122 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,
123                                     int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
124                                     int i_matrix_coefficients );
125
126 /*****************************************************************************
127  * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel convertion blocks
128  *****************************************************************************
129  * These convertion routines are used by YUV convertion functions.
130  * Convertion are made from p_y, p_u, p_v, which are modified, to p_buffer,
131  * which is also modified.
132  *****************************************************************************/
133 #define CONVERT_Y_PIXEL                                                       \
134     /* Only Y sample is present */                                            \
135     p_ybase = p_yuv + *p_y++;                                                 \
136     *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] |     \
137         p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT)       \
138         + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
139
140 #define CONVERT_YUV_PIXEL                                                     \
141     /* Y, U and V samples are present */                                      \
142     i_uval =    *p_u++;                                                       \
143     i_vval =    *p_v++;                                                       \
144     i_red =     (V_RED_COEF * i_vval) >> SHIFT;                               \
145     i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;     \
146     i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                              \
147     CONVERT_Y_PIXEL                                                           \
148
149 /*****************************************************************************
150  * SCALE_WIDTH: scale a line horizontally
151  *****************************************************************************
152  * This macro scale a line using rendering buffer and offset array.
153  *****************************************************************************/
154 #define SCALE_WIDTH                                                           \
155     if( b_horizontal_scaling )                                                \
156     {                                                                         \
157         /* Horizontal scaling, convertion has been done to buffer.            \
158          * Rewind buffer and offset, then copy and scale line */              \
159         p_buffer = p_buffer_start;                                            \
160         p_offset = p_offset_start;                                            \
161         for( i_x = i_pic_width / 16; i_x--; )                                 \
162         {                                                                     \
163             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
164             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
165             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
166             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
167             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
168             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
169             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
170             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
171             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
172             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
173             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
174             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
175             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
176             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
177             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
178             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
179         }                                                                     \
180         p_pic += i_pic_line_width;                                            \
181     }                                                                         \
182     else                                                                      \
183     {                                                                         \
184         /* No scaling, convertion has been done directly in picture memory.   \
185          * Increment of picture pointer to end of line is still needed */     \
186         p_pic += i_pic_width + i_pic_line_width;                              \
187     }                                                                         \
188
189 /*****************************************************************************
190  * SCALE_HEIGHT: handle vertical scaling
191  *****************************************************************************
192  * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
193  * 444 for RGB convertion, or 400 for gray convertion.
194  *****************************************************************************/
195 #define SCALE_HEIGHT( CHROMA )                                                \
196     /* If line is odd, rewind 4:2:0 U and V samples */                        \
197     if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
198     {                                                                         \
199         p_u -= i_chroma_width;                                                \
200         p_v -= i_chroma_width;                                                \
201     }                                                                         \
202                                                                               \
203     /*                                                                        \
204      * Handle vertical scaling. The current line can be copied or next one    \
205      * can be ignored.                                                        \
206      */                                                                       \
207     switch( i_vertical_scaling )                                              \
208     {                                                                         \
209     case -1:                             /* vertical scaling factor is < 1 */ \
210         while( (i_scale_count -= i_pic_height) >= 0 )                         \
211         {                                                                     \
212             /* Height reduction: skip next source line */                     \
213             p_y += i_width;                                                   \
214             i_y++;                                                            \
215             if( (CHROMA == 420) || (CHROMA == 422) )                          \
216             {                                                                 \
217                 if( i_y & 0x1 )                                               \
218                 {                                                             \
219                     p_u += i_chroma_width;                                    \
220                     p_v += i_chroma_width;                                    \
221                 }                                                             \
222             }                                                                 \
223             else if( CHROMA == 444 )                                          \
224             {                                                                 \
225                 p_u += i_width;                                               \
226                 p_v += i_width;                                               \
227             }                                                                 \
228         }                                                                     \
229         i_scale_count += i_height;                                            \
230         break;                                                                \
231     case 1:                              /* vertical scaling factor is > 1 */ \
232         while( (i_scale_count -= i_height) > 0 )                              \
233         {                                                                     \
234             /* Height increment: copy previous picture line */                \
235             for( i_x = i_pic_width / 16; i_x--; )                             \
236             {                                                                 \
237                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );           \
238                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );           \
239                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );           \
240                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );           \
241             }                                                                 \
242             p_pic +=        i_pic_line_width;                                 \
243             p_pic_start +=  i_pic_line_width;                                 \
244         }                                                                     \
245         i_scale_count += i_pic_height;                                        \
246         break;                                                                \
247     }                                                                         \
248
249 /*****************************************************************************
250  * vout_InitYUV: allocate and initialize translations tables
251  *****************************************************************************
252  * This function will allocate memory to store translation tables, depending
253  * of the screen depth.
254  *****************************************************************************/
255 int vout_InitYUV( vout_thread_t *p_vout )
256 {
257     size_t      tables_size;                        /* tables size, in bytes */
258     
259     /* Computes tables size */
260     switch( p_vout->i_screen_depth )
261     {
262     case 8:
263         tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
264         break;        
265     case 15:
266     case 16:
267         tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
268         break;        
269     case 24:        
270     case 32:
271 #ifndef DEBUG
272     default:        
273 #endif
274         tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);        
275         break;        
276 #ifdef DEBUG
277     default:
278         intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
279         tables_size = 0;
280         break;        
281 #endif      
282     }
283     
284     /* Allocate memory */
285     p_vout->yuv.p_base = malloc( tables_size );
286     if( p_vout->yuv.p_base == NULL )
287     {
288         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
289         return( 1 );                
290     }
291
292     /* Allocate memory for convertion buffer and offset array */
293     p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
294     if( p_vout->yuv.p_buffer == NULL )
295     {
296         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
297         free( p_vout->yuv.p_base );
298         return( 1 );                
299     }
300     p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );    
301     if( p_vout->yuv.p_offset == NULL )
302     {
303         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
304         free( p_vout->yuv.p_base );
305         free( p_vout->yuv.p_buffer );        
306         return( 1 );                
307     }
308
309     /* Initialize tables */
310     SetYUV( p_vout );
311     return( 0 );    
312 }
313
314 /*****************************************************************************
315  * vout_ResetTables: re-initialize translations tables
316  *****************************************************************************
317  * This function will initialize the tables allocated by vout_CreateTables and
318  * set functions pointers.
319  *****************************************************************************/
320 int vout_ResetYUV( vout_thread_t *p_vout )
321 {
322     vout_EndYUV( p_vout );    
323     return( vout_InitYUV( p_vout ) );    
324 }
325
326 /*****************************************************************************
327  * vout_EndYUV: destroy translations tables
328  *****************************************************************************
329  * Free memory allocated by vout_CreateTables.
330  *****************************************************************************/
331 void vout_EndYUV( vout_thread_t *p_vout )
332 {
333     free( p_vout->yuv.p_base );
334     free( p_vout->yuv.p_buffer );
335     free( p_vout->yuv.p_offset );    
336 }
337
338 /* following functions are local */
339
340 /*****************************************************************************
341  * BinaryLog: computes the base 2 log of a binary value
342  *****************************************************************************
343  * This functions is used by MaskToShift during tables initialisation, to
344  * get a bit index from a binary value.
345  *****************************************************************************/
346 static int BinaryLog(u32 i)
347 {
348     int i_log;
349
350     i_log = 0;
351     if (i & 0xffff0000) 
352     {        
353         i_log = 16;
354     }    
355     if (i & 0xff00ff00) 
356     {        
357         i_log += 8;
358     }    
359     if (i & 0xf0f0f0f0) 
360     {        
361         i_log += 4;
362     }    
363     if (i & 0xcccccccc) 
364     {        
365         i_log += 2;
366     }    
367     if (i & 0xaaaaaaaa) 
368     {        
369         i_log++;
370     }    
371     if (i != ((u32)1 << i_log))
372     {        
373         intf_ErrMsg("internal error: binary log overflow\n");        
374     }    
375
376     return( i_log );
377 }
378
379 /*****************************************************************************
380  * MaskToShift: Transform a color mask into right and left shifts
381  *****************************************************************************
382  * This function is used during table initialisation. It can return a value
383  *****************************************************************************/
384 static void MaskToShift (int *pi_right, int *pi_left, u32 i_mask)
385 {
386     u32 i_low, i_high;                 /* lower hand higher bits of the mask */
387
388     /* Get bits */
389     i_low =  i_mask & (- i_mask);                   /* lower bit of the mask */
390     i_high = i_mask + i_low;                       /* higher bit of the mask */
391
392     /* Transform bits into an index */
393     i_low =  BinaryLog (i_low);
394     i_high = BinaryLog (i_high);
395
396     /* Update pointers and return */
397     *pi_left =   i_low;
398     *pi_right = (8 - i_high + i_low);
399 }
400
401 /*****************************************************************************
402  * SetGammaTable: return intensity table transformed by gamma curve.
403  *****************************************************************************
404  * pi_table is a table of 256 entries from 0 to 255.
405  *****************************************************************************/
406 static void SetGammaTable( int *pi_table, double f_gamma )
407 {
408     int         i_y;                                       /* base intensity */
409
410     /* Use exp(gamma) instead of gamma */
411     f_gamma = exp(f_gamma );
412
413     /* Build gamma table */
414     for( i_y = 0; i_y < 256; i_y++ )
415     {
416         pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
417     }
418  }
419
420 /*****************************************************************************
421  * SetYUV: compute tables and set function pointers
422 + *****************************************************************************/
423 static void SetYUV( vout_thread_t *p_vout )
424 {
425     int         pi_gamma[256];                                /* gamma table */
426     int         i_index;                                  /* index in tables */
427     int         i_red_right, i_red_left;                       /* red shifts */
428     int         i_green_right, i_green_left;                 /* green shifts */
429     int         i_blue_right, i_blue_left;                    /* blue shifts */
430
431     /* Build gamma table */    
432     SetGammaTable( pi_gamma, p_vout->f_gamma );
433     
434     /*          
435      * Set color masks and shifts
436      */
437     switch( p_vout->i_screen_depth )
438     {
439     case 8:
440         MaskToShift( &i_red_right,   &i_red_left,   0xe0 );
441         MaskToShift( &i_green_right, &i_green_left, 0x1c );
442         MaskToShift( &i_blue_right,  &i_blue_left,  0x03 );        
443         break;        
444     case 15:
445         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
446         MaskToShift( &i_green_right, &i_green_left, 0x03e0 );
447         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );        
448         break;        
449     case 16:
450         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
451         MaskToShift( &i_green_right, &i_green_left, 0x07e0 );
452         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );
453         break;        
454     case 24:
455     case 32:        
456         MaskToShift( &i_red_right,   &i_red_left,   0x00ff0000 );
457         MaskToShift( &i_green_right, &i_green_left, 0x0000ff00 );
458         MaskToShift( &i_blue_right,  &i_blue_left,  0x000000ff );
459         break;
460 #ifdef DEBUG
461     default:
462         intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
463         break;        
464 #endif      
465     }
466
467     /*
468      * Set pointers and build YUV tables
469      */        
470     if( p_vout->b_grayscale )
471     {
472         /* Grayscale: build gray table */
473         switch( p_vout->i_screen_depth )
474         {
475         case 8:
476             p_vout->yuv.yuv.p_gray8 =  (u8 *)p_vout->yuv.p_base + GRAY_MARGIN;
477             break;        
478         case 15:
479         case 16:         
480             p_vout->yuv.yuv.p_gray16 =  (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
481             for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
482             {
483                 p_vout->yuv.yuv.p_gray16[ -i_index ] = 
484                     ((pi_gamma[ 0 ] >> i_red_right)   << i_red_left)   |
485                     ((pi_gamma[ 0 ] >> i_green_right) << i_green_left) |
486                     ((pi_gamma[ 0 ] >> i_blue_right)  << i_blue_left);
487                 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = 
488                     ((pi_gamma[ 255 ] >> i_red_right)   << i_red_left)   |
489                     ((pi_gamma[ 255 ] >> i_green_right) << i_green_left) |
490                     ((pi_gamma[ 255 ] >> i_blue_right)  << i_blue_left);
491             }            
492             for( i_index = 0; i_index < 256; i_index++) 
493             {
494                 p_vout->yuv.yuv.p_gray16[ i_index ] = 
495                     ((pi_gamma[ i_index ] >> i_red_right)   << i_red_left)   |
496                     ((pi_gamma[ i_index ] >> i_green_right) << i_green_left) |
497                     ((pi_gamma[ i_index ] >> i_blue_right)  << i_blue_left);
498             }
499             break;        
500         case 24:
501         case 32:        
502             p_vout->yuv.yuv.p_gray32 =  (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
503             for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
504             {
505                 p_vout->yuv.yuv.p_gray32[ -i_index ] = 
506                     ((pi_gamma[ 0 ] >> i_red_right)   << i_red_left)   |
507                     ((pi_gamma[ 0 ] >> i_green_right) << i_green_left) |
508                     ((pi_gamma[ 0 ] >> i_blue_right)  << i_blue_left);
509                 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = 
510                     ((pi_gamma[ 255 ] >> i_red_right)   << i_red_left)   |
511                     ((pi_gamma[ 255 ] >> i_green_right) << i_green_left) |
512                     ((pi_gamma[ 255 ] >> i_blue_right)  << i_blue_left);
513             }            
514             for( i_index = 0; i_index < 256; i_index++) 
515             {
516                 p_vout->yuv.yuv.p_gray32[ i_index ] = 
517                     ((pi_gamma[ i_index ] >> i_red_right)   << i_red_left)   |
518                     ((pi_gamma[ i_index ] >> i_green_right) << i_green_left) |
519                     ((pi_gamma[ i_index ] >> i_blue_right)  << i_blue_left);
520             }
521             break;        
522          }
523     }
524     else
525     {
526         /* Color: build red, green and blue tables */
527         switch( p_vout->i_screen_depth )
528         {
529         case 8:
530             p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
531             break;        
532         case 15:
533         case 16:            
534             p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
535             for( i_index = 0; i_index < RED_MARGIN; i_index++ )
536             {
537                 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
538                 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;                
539             }
540             for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
541             {
542                 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right) <<i_green_left;
543                 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
544             }
545             for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
546             {
547                 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
548                 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;                
549             }
550             for( i_index = 0; i_index < 256; i_index++ )
551             {
552                 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
553                 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
554                 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
555             }            
556             break;        
557         case 24:
558         case 32:
559             p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
560             for( i_index = 0; i_index < RED_MARGIN; i_index++ )
561             {
562                 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
563                 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;                
564             }
565             for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
566             {
567                 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right)<<i_green_left;
568                 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
569             }
570             for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
571             {
572                 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
573                 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;                
574             }
575             for( i_index = 0; i_index < 256; i_index++ )
576             {
577                 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
578                 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
579                 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
580             }            
581             break;        
582         }
583     }    
584
585     /*
586      * Set functions pointers
587      */
588     if( p_vout->b_grayscale )
589     {
590         /* Grayscale */
591         switch( p_vout->i_screen_depth )
592         {
593         case 8:
594             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;        
595             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;        
596             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;        
597             break;        
598         case 15:
599         case 16:  
600             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;        
601             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;        
602             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;        
603             break;        
604         case 24:
605             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;        
606             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;        
607             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;        
608             break;        
609         case 32:        
610             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;        
611             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;        
612             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;        
613             break;        
614         }        
615     }
616     else
617     {
618         /* Color */
619         switch( p_vout->i_screen_depth )
620         {
621         case 8:
622             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
623             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
624             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
625             break;        
626         case 15:
627         case 16:  
628             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB16;        
629             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB16;        
630             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB16;        
631             break;        
632         case 24:
633             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB24;        
634             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB24;        
635             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB24;        
636             break;        
637         case 32:        
638             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB32;        
639             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB32;        
640             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB32;        
641             break;        
642         }
643     }        
644 }
645
646 /*****************************************************************************
647  * SetOffset: build offset array for convertion functions
648  *****************************************************************************
649  * This function will build an offset array used in later convertion functions.
650  * It will also set horizontal and vertical scaling indicators.
651  *****************************************************************************/
652 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height, 
653                        boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
654 {    
655     int i_x;                                    /* x position in destination */
656     int i_scale_count;                                     /* modulo counter */
657
658     /*
659      * Prepare horizontal offset array
660      */      
661     if( i_pic_width - i_width > 0 )
662     {
663         /* Prepare scaling array for horizontal extension */
664         *pb_h_scaling =  1;   
665         i_scale_count =         i_pic_width;
666         for( i_x = i_width; i_x--; )
667         {
668             while( (i_scale_count -= i_width) > 0 )
669             {
670                 *p_offset++ = 0;                
671             }
672             *p_offset++ = 1;            
673             i_scale_count += i_pic_width;            
674         }        
675     }
676     else if( i_pic_width - i_width < 0 )
677     {
678         /* Prepare scaling array for horizontal reduction */
679         *pb_h_scaling =  1;
680         i_scale_count =         i_pic_width;
681         for( i_x = i_pic_width; i_x--; )
682         {
683             *p_offset = 1;            
684             while( (i_scale_count -= i_pic_width) >= 0 )
685             {                
686                 *p_offset += 1;                
687             }
688             p_offset++;
689             i_scale_count += i_width;
690         }        
691     }
692     else
693     {
694         /* No horizontal scaling: YUV convertion is done directly to picture */          
695         *pb_h_scaling = 0;        
696     }
697
698     /*
699      * Set vertical scaling indicator
700      */
701     if( i_pic_height - i_height > 0 )
702     {
703         *pi_v_scaling = 1;        
704     }
705     else if( i_pic_height - i_height < 0 )
706     {
707         *pi_v_scaling = -1;        
708     }
709     else
710     {
711         *pi_v_scaling = 0;        
712     }
713 }
714
715 /*****************************************************************************
716  * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
717  *****************************************************************************/
718 static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
719                             yuv_data_t *p_u, yuv_data_t *p_v, int i_width,
720                             int i_height, int i_pic_width, int i_pic_height,
721                             int i_pic_line_width, int i_matrix_coefficients )
722 {
723     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
724     int         i_vertical_scaling;                 /* vertical scaling type */
725     int         i_x, i_y;                 /* horizontal and vertical indexes */
726     int         i_scale_count;                       /* scale modulo counter */
727     int         i_chroma_width;                    /* chroma width, not used */
728     u8 *        p_gray;                             /* base convertion table */
729     u8 *        p_pic_start;       /* beginning of the current line for copy */
730     u8 *        p_buffer_start;                   /* convertion buffer start */
731     u8 *        p_buffer;                       /* convertion buffer pointer */
732     int *       p_offset_start;                        /* offset array start */
733     int *       p_offset;                            /* offset array pointer */
734     
735     /* 
736      * Initialize some values  - i_pic_line_width will store the line skip 
737      */
738     i_pic_line_width -= i_pic_width;                                            
739     p_gray =            p_vout->yuv.yuv.p_gray8;    
740     p_buffer_start =    p_vout->yuv.p_buffer;                                   
741     p_offset_start =    p_vout->yuv.p_offset;                                   
742     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
743                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
744
745     /*
746      * Perform convertion
747      */
748     i_scale_count = i_pic_height;
749     for( i_y = 0; i_y < i_height; i_y++ )
750     {
751         /* Mark beginnning of line for possible later line copy, and initialize
752          * buffer */
753         p_pic_start =   p_pic;
754         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
755
756         /* Do YUV convertion to buffer - YUV picture is always formed of 16
757          * pixels wide blocks */
758         for( i_x = i_width / 16; i_x--;  )
759         {
760             *p_buffer++ = p_gray[ *p_y++ ];
761             *p_buffer++ = p_gray[ *p_y++ ];
762             *p_buffer++ = p_gray[ *p_y++ ];
763             *p_buffer++ = p_gray[ *p_y++ ];
764             *p_buffer++ = p_gray[ *p_y++ ];
765             *p_buffer++ = p_gray[ *p_y++ ];
766             *p_buffer++ = p_gray[ *p_y++ ];
767             *p_buffer++ = p_gray[ *p_y++ ];
768             *p_buffer++ = p_gray[ *p_y++ ];
769             *p_buffer++ = p_gray[ *p_y++ ];
770             *p_buffer++ = p_gray[ *p_y++ ];
771             *p_buffer++ = p_gray[ *p_y++ ];
772             *p_buffer++ = p_gray[ *p_y++ ];
773             *p_buffer++ = p_gray[ *p_y++ ];
774             *p_buffer++ = p_gray[ *p_y++ ];
775             *p_buffer++ = p_gray[ *p_y++ ];
776         }             
777
778         /* Do horizontal and vertical scaling */
779         SCALE_WIDTH;
780         SCALE_HEIGHT(400);        
781     }
782 }
783
784 /*****************************************************************************
785  * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 15 or 16 bpp
786  *****************************************************************************/
787 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,
788                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
789                              int i_matrix_coefficients )
790 {
791     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
792     int         i_vertical_scaling;                 /* vertical scaling type */
793     int         i_x, i_y;                 /* horizontal and vertical indexes */
794     int         i_scale_count;                       /* scale modulo counter */
795     int         i_chroma_width;                    /* chroma width, not used */
796     u16 *       p_gray;                             /* base convertion table */
797     u16 *       p_pic_start;       /* beginning of the current line for copy */
798     u16 *       p_buffer_start;                   /* convertion buffer start */
799     u16 *       p_buffer;                       /* convertion buffer pointer */
800     int *       p_offset_start;                        /* offset array start */
801     int *       p_offset;                            /* offset array pointer */
802     
803     /* 
804      * Initialize some values  - i_pic_line_width will store the line skip 
805      */
806     i_pic_line_width -= i_pic_width;                                            
807     p_gray =            p_vout->yuv.yuv.p_gray16;    
808     p_buffer_start =    p_vout->yuv.p_buffer;                                   
809     p_offset_start =    p_vout->yuv.p_offset;                                   
810     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
811                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
812
813     /*
814      * Perform convertion
815      */
816     i_scale_count = i_pic_height;
817     for( i_y = 0; i_y < i_height; i_y++ )
818     {
819         /* Mark beginnning of line for possible later line copy, and initialize
820          * buffer */
821         p_pic_start =   p_pic;
822         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
823
824         /* Do YUV convertion to buffer - YUV picture is always formed of 16
825          * pixels wide blocks */
826         for( i_x = i_width / 16; i_x--;  )
827         {
828             *p_buffer++ = p_gray[ *p_y++ ];
829             *p_buffer++ = p_gray[ *p_y++ ];
830             *p_buffer++ = p_gray[ *p_y++ ];
831             *p_buffer++ = p_gray[ *p_y++ ];
832             *p_buffer++ = p_gray[ *p_y++ ];
833             *p_buffer++ = p_gray[ *p_y++ ];
834             *p_buffer++ = p_gray[ *p_y++ ];
835             *p_buffer++ = p_gray[ *p_y++ ];
836             *p_buffer++ = p_gray[ *p_y++ ];
837             *p_buffer++ = p_gray[ *p_y++ ];
838             *p_buffer++ = p_gray[ *p_y++ ];
839             *p_buffer++ = p_gray[ *p_y++ ];
840             *p_buffer++ = p_gray[ *p_y++ ];
841             *p_buffer++ = p_gray[ *p_y++ ];
842             *p_buffer++ = p_gray[ *p_y++ ];
843             *p_buffer++ = p_gray[ *p_y++ ];
844         }             
845
846         /* Do horizontal and vertical scaling */
847         SCALE_WIDTH;
848         SCALE_HEIGHT(400);        
849     }
850 }
851
852 /*****************************************************************************
853  * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 24 bpp
854  *****************************************************************************/
855 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,
856                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
857                              int i_matrix_coefficients )
858 {
859     //??
860 }
861
862 /*****************************************************************************
863  * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 32 bpp
864  *****************************************************************************/
865 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,
866                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
867                              int i_matrix_coefficients )
868 {
869     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
870     int         i_vertical_scaling;                 /* vertical scaling type */
871     int         i_x, i_y;                 /* horizontal and vertical indexes */
872     int         i_scale_count;                       /* scale modulo counter */
873     int         i_chroma_width;                    /* chroma width, not used */
874     u32 *       p_gray;                             /* base convertion table */
875     u32 *       p_pic_start;       /* beginning of the current line for copy */
876     u32 *       p_buffer_start;                   /* convertion buffer start */
877     u32 *       p_buffer;                       /* convertion buffer pointer */
878     int *       p_offset_start;                        /* offset array start */
879     int *       p_offset;                            /* offset array pointer */
880     
881     /* 
882      * Initialize some values  - i_pic_line_width will store the line skip 
883      */
884     i_pic_line_width -= i_pic_width;                                            
885     p_gray =            p_vout->yuv.yuv.p_gray32;    
886     p_buffer_start =    p_vout->yuv.p_buffer;                                   
887     p_offset_start =    p_vout->yuv.p_offset;                                   
888     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
889                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
890
891     /*
892      * Perform convertion
893      */
894     i_scale_count = i_pic_height;
895     for( i_y = 0; i_y < i_height; i_y++ )
896     {
897         /* Mark beginnning of line for possible later line copy, and initialize
898          * buffer */
899         p_pic_start =   p_pic;
900         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
901
902         /* Do YUV convertion to buffer - YUV picture is always formed of 16
903          * pixels wide blocks */
904         for( i_x = i_width / 16; i_x--;  )
905         {
906             *p_buffer++ = p_gray[ *p_y++ ];
907             *p_buffer++ = p_gray[ *p_y++ ];
908             *p_buffer++ = p_gray[ *p_y++ ];
909             *p_buffer++ = p_gray[ *p_y++ ];
910             *p_buffer++ = p_gray[ *p_y++ ];
911             *p_buffer++ = p_gray[ *p_y++ ];
912             *p_buffer++ = p_gray[ *p_y++ ];
913             *p_buffer++ = p_gray[ *p_y++ ];
914             *p_buffer++ = p_gray[ *p_y++ ];
915             *p_buffer++ = p_gray[ *p_y++ ];
916             *p_buffer++ = p_gray[ *p_y++ ];
917             *p_buffer++ = p_gray[ *p_y++ ];
918             *p_buffer++ = p_gray[ *p_y++ ];
919             *p_buffer++ = p_gray[ *p_y++ ];
920             *p_buffer++ = p_gray[ *p_y++ ];
921             *p_buffer++ = p_gray[ *p_y++ ];
922         }             
923
924         /* Do horizontal and vertical scaling */
925         SCALE_WIDTH;
926         SCALE_HEIGHT(400);        
927     }
928 }
929
930 /*****************************************************************************
931  * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
932  *****************************************************************************/
933 static void ConvertYUV420RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
934                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
935                                 int i_matrix_coefficients )
936 {
937     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
938     int         i_vertical_scaling;                 /* vertical scaling type */
939     int         i_x, i_y;                 /* horizontal and vertical indexes */
940     int         i_scale_count;                       /* scale modulo counter */
941     int         i_uval, i_vval;                           /* U and V samples */
942     int         i_red, i_green, i_blue;          /* U and V modified samples */
943     int         i_chroma_width;                              /* chroma width */
944     u8 *        p_yuv;                              /* base convertion table */
945     u8 *        p_ybase;                     /* Y dependant convertion table */
946     u8 *        p_pic_start;       /* beginning of the current line for copy */
947     u8 *        p_buffer_start;                   /* convertion buffer start */
948     u8 *        p_buffer;                       /* convertion buffer pointer */
949     int *       p_offset_start;                        /* offset array start */
950     int *       p_offset;                            /* offset array pointer */
951     
952     /* 
953      * Initialize some values  - i_pic_line_width will store the line skip 
954      */
955     i_pic_line_width -= i_pic_width;
956     i_chroma_width =    i_width / 2;
957     p_yuv =             p_vout->yuv.yuv.p_rgb8;
958     p_buffer_start =    p_vout->yuv.p_buffer;        
959     p_offset_start =    p_vout->yuv.p_offset;                    
960     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
961                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
962
963     /*
964      * Perform convertion
965      */
966     i_scale_count = i_pic_height;
967     for( i_y = 0; i_y < i_height; i_y++ )
968     {
969         /* Mark beginnning of line for possible later line copy, and initialize
970          * buffer */
971         p_pic_start =   p_pic;
972         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
973
974         /* Do YUV convertion to buffer - YUV picture is always formed of 16
975          * pixels wide blocks */
976         for( i_x = i_width / 16; i_x--;  )
977         {
978             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
979             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
980             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
981             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
982             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
983             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
984             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
985             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
986         }             
987
988         /* Do horizontal and vertical scaling */
989         SCALE_WIDTH;
990         SCALE_HEIGHT(420);        
991     }
992 }
993
994 /*****************************************************************************
995  * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
996  *****************************************************************************/
997 static void ConvertYUV422RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
998                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
999                                 int i_matrix_coefficients )
1000 {
1001     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1002     int         i_vertical_scaling;                 /* vertical scaling type */
1003     int         i_x, i_y;                 /* horizontal and vertical indexes */
1004     int         i_scale_count;                       /* scale modulo counter */
1005     int         i_uval, i_vval;                           /* U and V samples */
1006     int         i_red, i_green, i_blue;          /* U and V modified samples */
1007     int         i_chroma_width;                              /* chroma width */
1008     u8 *        p_yuv;                              /* base convertion table */
1009     u8 *        p_ybase;                     /* Y dependant convertion table */
1010     u8 *        p_pic_start;       /* beginning of the current line for copy */
1011     u8 *        p_buffer_start;                   /* convertion buffer start */
1012     u8 *        p_buffer;                       /* convertion buffer pointer */
1013     int *       p_offset_start;                        /* offset array start */
1014     int *       p_offset;                            /* offset array pointer */
1015     
1016     /* 
1017      * Initialize some values  - i_pic_line_width will store the line skip 
1018      */
1019     i_pic_line_width -= i_pic_width;
1020     i_chroma_width =    i_width / 2;
1021     p_yuv =             p_vout->yuv.yuv.p_rgb8;
1022     p_buffer_start =    p_vout->yuv.p_buffer;        
1023     p_offset_start =    p_vout->yuv.p_offset;                    
1024     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1025                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1026
1027     /*
1028      * Perform convertion
1029      */
1030     i_scale_count = i_pic_height;
1031     for( i_y = 0; i_y < i_height; i_y++ )
1032     {
1033         /* Mark beginnning of line for possible later line copy, and initialize
1034          * buffer */
1035         p_pic_start =   p_pic;
1036         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1037
1038         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1039          * pixels wide blocks */
1040         for( i_x = i_width / 16; i_x--;  )
1041         {
1042             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1043             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1044             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1045             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1046             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1047             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1048             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1049             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1050         }             
1051
1052         /* Do horizontal and vertical scaling */
1053         SCALE_WIDTH;
1054         SCALE_HEIGHT(422);        
1055     }
1056 }
1057
1058 /*****************************************************************************
1059  * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1060  *****************************************************************************/
1061 static void ConvertYUV444RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1062                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1063                                 int i_matrix_coefficients )
1064 {
1065     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1066     int         i_vertical_scaling;                 /* vertical scaling type */
1067     int         i_x, i_y;                 /* horizontal and vertical indexes */
1068     int         i_scale_count;                       /* scale modulo counter */
1069     int         i_uval, i_vval;                           /* U and V samples */
1070     int         i_red, i_green, i_blue;          /* U and V modified samples */
1071     int         i_chroma_width;                    /* chroma width, not used */
1072     u8 *        p_yuv;                              /* base convertion table */
1073     u8 *        p_ybase;                     /* Y dependant convertion table */
1074     u8 *        p_pic_start;       /* beginning of the current line for copy */
1075     u8 *        p_buffer_start;                   /* convertion buffer start */
1076     u8 *        p_buffer;                       /* convertion buffer pointer */
1077     int *       p_offset_start;                        /* offset array start */
1078     int *       p_offset;                            /* offset array pointer */
1079     
1080     /* 
1081      * Initialize some values  - i_pic_line_width will store the line skip 
1082      */
1083     i_pic_line_width -= i_pic_width;
1084     p_yuv =             p_vout->yuv.yuv.p_rgb8;
1085     p_buffer_start =    p_vout->yuv.p_buffer;        
1086     p_offset_start =    p_vout->yuv.p_offset;                    
1087     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1088                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1089
1090     /*
1091      * Perform convertion
1092      */
1093     i_scale_count = i_pic_height;
1094     for( i_y = 0; i_y < i_height; i_y++ )
1095     {
1096         /* Mark beginnning of line for possible later line copy, and initialize
1097          * buffer */
1098         p_pic_start =   p_pic;
1099         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1100
1101         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1102          * pixels wide blocks */
1103         for( i_x = i_width / 16; i_x--;  )
1104         {
1105             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1106             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1107             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1108             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1109             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1110             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1111             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1112             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1113         }             
1114
1115         /* Do horizontal and vertical scaling */
1116         SCALE_WIDTH;
1117         SCALE_HEIGHT(444);        
1118     }
1119 }
1120
1121 /*****************************************************************************
1122  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 15 or 16 bpp
1123  *****************************************************************************/
1124 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,
1125                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1126                                 int i_matrix_coefficients )
1127 {
1128 /* MMX version */
1129   //  int                 i_chroma_width, i_chroma_skip;      /* width and eol for chroma */
1130 /*
1131     i_chroma_width =    i_width / 2;
1132     i_chroma_skip =     i_skip / 2;
1133     ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height, 
1134                            (i_width + i_skip) * sizeof( yuv_data_t ), 
1135                            (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1136                            i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1137                            p_vout->i_screen_depth == 15 );    
1138 */
1139     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1140     int         i_vertical_scaling;                 /* vertical scaling type */
1141     int         i_x, i_y;                 /* horizontal and vertical indexes */
1142     int         i_scale_count;                       /* scale modulo counter */
1143     int         i_uval, i_vval;                           /* U and V samples */
1144     int         i_red, i_green, i_blue;          /* U and V modified samples */
1145     int         i_chroma_width;                              /* chroma width */
1146     u16 *       p_yuv;                              /* base convertion table */
1147     u16 *       p_ybase;                     /* Y dependant convertion table */
1148     u16 *       p_pic_start;       /* beginning of the current line for copy */
1149     u16 *       p_buffer_start;                   /* convertion buffer start */
1150     u16 *       p_buffer;                       /* convertion buffer pointer */
1151     int *       p_offset_start;                        /* offset array start */
1152     int *       p_offset;                            /* offset array pointer */
1153     
1154     /* 
1155      * Initialize some values  - i_pic_line_width will store the line skip 
1156      */
1157     i_pic_line_width -= i_pic_width;
1158     i_chroma_width =    i_width / 2;
1159     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1160     p_buffer_start =    p_vout->yuv.p_buffer;        
1161     p_offset_start =    p_vout->yuv.p_offset;                    
1162     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1163                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1164
1165     /*
1166      * Perform convertion
1167      */
1168     i_scale_count = i_pic_height;
1169     for( i_y = 0; i_y < i_height; i_y++ )
1170     {
1171         /* Mark beginnning of line for possible later line copy, and initialize
1172          * buffer */
1173         p_pic_start =   p_pic;
1174         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1175
1176         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1177          * pixels wide blocks */
1178         for( i_x = i_width / 16; i_x--;  )
1179         {
1180             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1181             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1182             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1183             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1184             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1185             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1186             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1187             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1188         }             
1189
1190         /* Do horizontal and vertical scaling */
1191         SCALE_WIDTH;
1192         SCALE_HEIGHT(420);        
1193     }
1194 }
1195
1196 /*****************************************************************************
1197  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 15 or 16 bpp
1198  *****************************************************************************/
1199 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,
1200                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1201                                 int i_matrix_coefficients )
1202 {
1203     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1204     int         i_vertical_scaling;                 /* vertical scaling type */
1205     int         i_x, i_y;                 /* horizontal and vertical indexes */
1206     int         i_scale_count;                       /* scale modulo counter */
1207     int         i_uval, i_vval;                           /* U and V samples */
1208     int         i_red, i_green, i_blue;          /* U and V modified samples */
1209     int         i_chroma_width;                              /* chroma width */
1210     u16 *       p_yuv;                              /* base convertion table */
1211     u16 *       p_ybase;                     /* Y dependant convertion table */
1212     u16 *       p_pic_start;       /* beginning of the current line for copy */
1213     u16 *       p_buffer_start;                   /* convertion buffer start */
1214     u16 *       p_buffer;                       /* convertion buffer pointer */
1215     int *       p_offset_start;                        /* offset array start */
1216     int *       p_offset;                            /* offset array pointer */
1217     
1218     /* 
1219      * Initialize some values  - i_pic_line_width will store the line skip 
1220      */
1221     i_pic_line_width -= i_pic_width;
1222     i_chroma_width =    i_width / 2;
1223     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1224     p_buffer_start =    p_vout->yuv.p_buffer;        
1225     p_offset_start =    p_vout->yuv.p_offset;                    
1226     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1227                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1228
1229     /*
1230      * Perform convertion
1231      */
1232     i_scale_count = i_pic_height;
1233     for( i_y = 0; i_y < i_height; i_y++ )
1234     {
1235         /* Mark beginnning of line for possible later line copy, and initialize
1236          * buffer */
1237         p_pic_start =   p_pic;
1238         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1239
1240         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1241          * pixels wide blocks */
1242         for( i_x = i_width / 16; i_x--;  )
1243         {
1244             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1245             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1246             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1247             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1248             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1249             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1250             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1251             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1252         }             
1253
1254         /* Do horizontal and vertical scaling */
1255         SCALE_WIDTH;
1256         SCALE_HEIGHT(422);        
1257     }
1258 }
1259
1260 /*****************************************************************************
1261  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 15 or 16 bpp
1262  *****************************************************************************/
1263 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,
1264                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1265                                 int i_matrix_coefficients )
1266 {
1267     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1268     int         i_vertical_scaling;                 /* vertical scaling type */
1269     int         i_x, i_y;                 /* horizontal and vertical indexes */
1270     int         i_scale_count;                       /* scale modulo counter */
1271     int         i_uval, i_vval;                           /* U and V samples */
1272     int         i_red, i_green, i_blue;          /* U and V modified samples */
1273     int         i_chroma_width;                    /* chroma width, not used */
1274     u16 *       p_yuv;                              /* base convertion table */
1275     u16 *       p_ybase;                     /* Y dependant convertion table */
1276     u16 *       p_pic_start;       /* beginning of the current line for copy */
1277     u16 *       p_buffer_start;                   /* convertion buffer start */
1278     u16 *       p_buffer;                       /* convertion buffer pointer */
1279     int *       p_offset_start;                        /* offset array start */
1280     int *       p_offset;                            /* offset array pointer */
1281     
1282     /* 
1283      * Initialize some values  - i_pic_line_width will store the line skip 
1284      */
1285     i_pic_line_width -= i_pic_width;
1286     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1287     p_buffer_start =    p_vout->yuv.p_buffer;        
1288     p_offset_start =    p_vout->yuv.p_offset;                    
1289     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1290                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1291
1292     /*
1293      * Perform convertion
1294      */
1295     i_scale_count = i_pic_height;
1296     for( i_y = 0; i_y < i_height; i_y++ )
1297     {
1298         /* Mark beginnning of line for possible later line copy, and initialize
1299          * buffer */
1300         p_pic_start =   p_pic;
1301         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1302
1303         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1304          * pixels wide blocks */
1305         for( i_x = i_width / 16; i_x--;  )
1306         {
1307             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1308             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1309             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1310             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1311             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1312             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1313             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1314             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1315         }             
1316
1317         /* Do horizontal and vertical scaling */
1318         SCALE_WIDTH;
1319         SCALE_HEIGHT(444);        
1320     }
1321 }
1322
1323 /*****************************************************************************
1324  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 24 bpp
1325  *****************************************************************************/
1326 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,
1327                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1328                                 int i_matrix_coefficients )
1329 {
1330     //???
1331 }
1332
1333 /*****************************************************************************
1334  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 24 bpp
1335  *****************************************************************************/
1336 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,
1337                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1338                                 int i_matrix_coefficients )
1339 {
1340     //???
1341 }
1342
1343 /*****************************************************************************
1344  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 24 bpp
1345  *****************************************************************************/
1346 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,
1347                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1348                                 int i_matrix_coefficients )
1349 {    
1350     //???
1351 }
1352
1353 /*****************************************************************************
1354  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 32 bpp
1355  *****************************************************************************/
1356 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,
1357                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1358                                 int i_matrix_coefficients )
1359 {
1360     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1361     int         i_vertical_scaling;                 /* vertical scaling type */
1362     int         i_x, i_y;                 /* horizontal and vertical indexes */
1363     int         i_scale_count;                       /* scale modulo counter */
1364     int         i_uval, i_vval;                           /* U and V samples */
1365     int         i_red, i_green, i_blue;          /* U and V modified samples */
1366     int         i_chroma_width;                              /* chroma width */
1367     u32 *       p_yuv;                              /* base convertion table */
1368     u32 *       p_ybase;                     /* Y dependant convertion table */
1369     u32 *       p_pic_start;       /* beginning of the current line for copy */
1370     u32 *       p_buffer_start;                   /* convertion buffer start */
1371     u32 *       p_buffer;                       /* convertion buffer pointer */
1372     int *       p_offset_start;                        /* offset array start */
1373     int *       p_offset;                            /* offset array pointer */
1374     
1375     /* 
1376      * Initialize some values  - i_pic_line_width will store the line skip 
1377      */
1378     i_pic_line_width -= i_pic_width;
1379     i_chroma_width =    i_width / 2;
1380     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1381     p_buffer_start =    p_vout->yuv.p_buffer;        
1382     p_offset_start =    p_vout->yuv.p_offset;                    
1383     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1384                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1385
1386     /*
1387      * Perform convertion
1388      */
1389     i_scale_count = i_pic_height;
1390     for( i_y = 0; i_y < i_height; i_y++ )
1391     {
1392         /* Mark beginnning of line for possible later line copy, and initialize
1393          * buffer */
1394         p_pic_start =   p_pic;
1395         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1396
1397         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1398          * pixels wide blocks */
1399         for( i_x = i_width / 16; i_x--;  )
1400         {
1401             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1402             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1403             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1404             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1405             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1406             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1407             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1408             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1409         }             
1410
1411         /* Do horizontal and vertical scaling */
1412         SCALE_WIDTH;
1413         SCALE_HEIGHT(420);        
1414     }
1415 }
1416
1417 /*****************************************************************************
1418  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 32 bpp
1419  *****************************************************************************/
1420 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,
1421                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1422                                 int i_matrix_coefficients )
1423 {
1424     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1425     int         i_vertical_scaling;                 /* vertical scaling type */
1426     int         i_x, i_y;                 /* horizontal and vertical indexes */
1427     int         i_scale_count;                       /* scale modulo counter */
1428     int         i_uval, i_vval;                           /* U and V samples */
1429     int         i_red, i_green, i_blue;          /* U and V modified samples */
1430     int         i_chroma_width;                              /* chroma width */
1431     u32 *       p_yuv;                              /* base convertion table */
1432     u32 *       p_ybase;                     /* Y dependant convertion table */
1433     u32 *       p_pic_start;       /* beginning of the current line for copy */
1434     u32 *       p_buffer_start;                   /* convertion buffer start */
1435     u32 *       p_buffer;                       /* convertion buffer pointer */
1436     int *       p_offset_start;                        /* offset array start */
1437     int *       p_offset;                            /* offset array pointer */
1438     
1439     /* 
1440      * Initialize some values  - i_pic_line_width will store the line skip 
1441      */
1442     i_pic_line_width -= i_pic_width;
1443     i_chroma_width =    i_width / 2;
1444     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1445     p_buffer_start =    p_vout->yuv.p_buffer;        
1446     p_offset_start =    p_vout->yuv.p_offset;                    
1447     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1448                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1449
1450     /*
1451      * Perform convertion
1452      */
1453     i_scale_count = i_pic_height;
1454     for( i_y = 0; i_y < i_height; i_y++ )
1455     {
1456         /* Mark beginnning of line for possible later line copy, and initialize
1457          * buffer */
1458         p_pic_start =   p_pic;
1459         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1460
1461         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1462          * pixels wide blocks */
1463         for( i_x = i_width / 16; i_x--;  )
1464         {
1465             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1466             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1467             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1468             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1469             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1470             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1471             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1472             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1473         }             
1474
1475         /* Do horizontal and vertical scaling */
1476         SCALE_WIDTH;
1477         SCALE_HEIGHT(422);        
1478     }
1479 }
1480
1481 /*****************************************************************************
1482  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 32 bpp
1483  *****************************************************************************/
1484 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,
1485                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1486                                 int i_matrix_coefficients )
1487 {
1488     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1489     int         i_vertical_scaling;                 /* vertical scaling type */
1490     int         i_x, i_y;                 /* horizontal and vertical indexes */
1491     int         i_scale_count;                       /* scale modulo counter */
1492     int         i_uval, i_vval;                           /* U and V samples */
1493     int         i_red, i_green, i_blue;          /* U and V modified samples */
1494     int         i_chroma_width;                    /* chroma width, not used */
1495     u32 *       p_yuv;                              /* base convertion table */
1496     u32 *       p_ybase;                     /* Y dependant convertion table */
1497     u32 *       p_pic_start;       /* beginning of the current line for copy */
1498     u32 *       p_buffer_start;                   /* convertion buffer start */
1499     u32 *       p_buffer;                       /* convertion buffer pointer */
1500     int *       p_offset_start;                        /* offset array start */
1501     int *       p_offset;                            /* offset array pointer */
1502     
1503     /* 
1504      * Initialize some values  - i_pic_line_width will store the line skip 
1505      */
1506     i_pic_line_width -= i_pic_width;
1507     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1508     p_buffer_start =    p_vout->yuv.p_buffer;        
1509     p_offset_start =    p_vout->yuv.p_offset;                    
1510     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1511                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1512
1513     /*
1514      * Perform convertion
1515      */
1516     i_scale_count = i_pic_height;
1517     for( i_y = 0; i_y < i_height; i_y++ )
1518     {
1519         /* Mark beginnning of line for possible later line copy, and initialize
1520          * buffer */
1521         p_pic_start =   p_pic;
1522         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1523
1524         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1525          * pixels wide blocks */
1526         for( i_x = i_width / 16; i_x--;  )
1527         {
1528             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1529             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1530             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1531             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1532             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1533             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1534             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1535             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1536         }             
1537
1538         /* Do horizontal and vertical scaling */
1539         SCALE_WIDTH;
1540         SCALE_HEIGHT(444);        
1541     }
1542 }
1543
1544 //-------------------- walken code follows ------------------------------------
1545
1546 /*
1547  * YUV to RGB routines.
1548  *
1549  * these routines calculate r, g and b values from each pixel's y, u and v.
1550  * these r, g an b values are then passed thru a table lookup to take the
1551  * gamma curve into account and find the corresponding pixel value.
1552  *
1553  * the table must store more than 3*256 values because of the possibility
1554  * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1555  * values are in the following intervals :
1556  * -176 to 255+176 for red
1557  * -133 to 255+133 for green
1558  * -222 to 255+222 for blue
1559  *
1560  * If the input y,u,v values are right, the r,g,b results are not expected
1561  * to move out of the 0 to 255 interval but who knows what will happen in
1562  * real use...
1563  *
1564  * the red, green and blue conversion tables are stored in a single 1935-entry
1565  * array. The respective positions of each component in the array have been
1566  * calculated to minimize the cache interactions of the 3 tables.
1567  */
1568
1569 #if 0
1570 static void yuvToRgb24 (unsigned char * Y,
1571                         unsigned char * U, unsigned char * V,
1572                         char * dest, int table[1935], int width)
1573 {
1574     int i;
1575     int u;
1576     int v;
1577     int uvRed;
1578     int uvGreen;
1579     int uvBlue;
1580     int * tableY;
1581     int tmp24;
1582
1583     i = width >> 3;
1584     while (i--) {
1585         u = *(U++);
1586         v = *(V++);
1587         uvRed = (V_RED_COEF*v) >> SHIFT;
1588         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1589         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1590
1591         tableY = table + *(Y++);
1592         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1593                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1594                         uvGreen] |
1595                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1596         *(dest++) = tmp24;
1597         *(dest++) = tmp24 >> 8;
1598         *(dest++) = tmp24 >> 16;
1599
1600         tableY = table + *(Y++);
1601         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1602                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1603                         uvGreen] |
1604                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1605         *(dest++) = tmp24;
1606         *(dest++) = tmp24 >> 8;
1607         *(dest++) = tmp24 >> 16;
1608
1609         u = *(U++);
1610         v = *(V++);
1611         uvRed = (V_RED_COEF*v) >> SHIFT;
1612         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1613         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1614
1615         tableY = table + *(Y++);
1616         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1617                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1618                         uvGreen] |
1619                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1620         *(dest++) = tmp24;
1621         *(dest++) = tmp24 >> 8;
1622         *(dest++) = tmp24 >> 16;
1623
1624         tableY = table + *(Y++);
1625         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1626                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1627                         uvGreen] |
1628                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1629         *(dest++) = tmp24;
1630         *(dest++) = tmp24 >> 8;
1631         *(dest++) = tmp24 >> 16;
1632
1633         u = *(U++);
1634         v = *(V++);
1635         uvRed = (V_RED_COEF*v) >> SHIFT;
1636         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1637         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1638
1639         tableY = table + *(Y++);
1640         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1641                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1642                         uvGreen] |
1643                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1644         *(dest++) = tmp24;
1645         *(dest++) = tmp24 >> 8;
1646         *(dest++) = tmp24 >> 16;
1647
1648         tableY = table + *(Y++);
1649         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1650                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1651                         uvGreen] |
1652                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1653         *(dest++) = tmp24;
1654         *(dest++) = tmp24 >> 8;
1655         *(dest++) = tmp24 >> 16;
1656
1657         u = *(U++);
1658         v = *(V++);
1659         uvRed = (V_RED_COEF*v) >> SHIFT;
1660         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1661         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1662
1663         tableY = table + *(Y++);
1664         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1665                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1666                         uvGreen] |
1667                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1668         *(dest++) = tmp24;
1669         *(dest++) = tmp24 >> 8;
1670         *(dest++) = tmp24 >> 16;
1671
1672         tableY = table + *(Y++);
1673         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1674                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1675                         uvGreen] |
1676                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1677         *(dest++) = tmp24;
1678         *(dest++) = tmp24 >> 8;
1679         *(dest++) = tmp24 >> 16;
1680     }
1681
1682     i = (width & 7) >> 1;
1683     while (i--) {
1684         u = *(U++);
1685         v = *(V++);
1686         uvRed = (V_RED_COEF*v) >> SHIFT;
1687         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1688         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1689
1690         tableY = table + *(Y++);
1691         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1692                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1693                         uvGreen] |
1694                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1695         *(dest++) = tmp24;
1696         *(dest++) = tmp24 >> 8;
1697         *(dest++) = tmp24 >> 16;
1698
1699         tableY = table + *(Y++);
1700         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1701                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1702                         uvGreen] |
1703                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1704         *(dest++) = tmp24;
1705         *(dest++) = tmp24 >> 8;
1706         *(dest++) = tmp24 >> 16;
1707     }
1708
1709     if (width & 1) {
1710         u = *(U++);
1711         v = *(V++);
1712         uvRed = (V_RED_COEF*v) >> SHIFT;
1713         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1714         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1715
1716         tableY = table + *(Y++);
1717         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1718                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1719                         uvGreen] |
1720                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1721         *(dest++) = tmp24;
1722         *(dest++) = tmp24 >> 8;
1723         *(dest++) = tmp24 >> 16;
1724     }
1725 }
1726 #endif