]> git.sesse.net Git - vlc/blob - src/video_output/video_yuv.c
Support 4:2:2, 4:4:4 et niveaux de gris en 15, 16 et 32 bpp complet.
[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     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,
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     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,
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     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,
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     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,
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     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,
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     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,
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     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,
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     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,
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     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,
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     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,
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     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,
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     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,
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
114 /*******************************************************************************
115  * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel convertion blocks
116  *******************************************************************************
117  * These convertion routines are used by YUV convertion functions.
118  * Convertion are made from p_y, p_u, p_v, which are modified, to p_buffer,
119  * which is also modified.
120  *******************************************************************************/
121 #define CONVERT_Y_PIXEL                                                                 \
122     /* Only Y sample is present */                                                      \
123     p_ybase = p_yuv + *p_y++;                                                           \
124     *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] |               \
125         p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |   \
126         p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];                       \
127
128 #define CONVERT_YUV_PIXEL                                                       \
129     /* Y, U and V samples are present */                                        \
130     i_uval =    *p_u++;                                                         \
131     i_vval =    *p_v++;                                                         \
132     i_red =     (V_RED_COEF * i_vval) >> SHIFT;                                 \
133     i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;       \
134     i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                                \
135     CONVERT_Y_PIXEL                                                             \
136
137 /*******************************************************************************
138  * SCALE_WIDTH: scale a line horizontally
139  *******************************************************************************
140  * This macro scale a line using rendering buffer and offset array.
141  *******************************************************************************/
142 #define SCALE_WIDTH                                                             \
143     if( b_horizontal_scaling )                                                  \
144     {                                                                           \
145         /* Horizontal scaling, convertion has been done to buffer.              \
146          * Rewind buffer and offset, then copy and scale line */                \
147         p_buffer = p_buffer_start;                                              \
148         p_offset = p_offset_start;                                              \
149         for( i_x = i_pic_width / 16; i_x--; )                                   \
150         {                                                                       \
151             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
152             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
153             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
154             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
155             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
156             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
157             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
158             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
159             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
160             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
161             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
162             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                    \
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         }                                                                       \
168         p_pic += i_pic_line_width;                                              \
169     }                                                                           \
170     else                                                                        \
171     {                                                                           \
172         /* No scaling, convertion has been done directly in picture memory.     \
173          * Increment of picture pointer to end of line is still needed */       \
174         p_pic += i_pic_width + i_pic_line_width;                                \
175     }                                                                           \
176
177 /*******************************************************************************
178  * SCALE_HEIGHT: handle vertical scaling
179  *******************************************************************************
180  * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
181  * 444 for RGB convertion, or 400 for gray convertion.
182  *******************************************************************************/
183 #define SCALE_HEIGHT( CHROMA )                                                  \
184     /* If line is odd, rewind 4:2:0 U and V samples */                          \
185     if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                  \
186     {                                                                           \
187         p_u -= i_chroma_width;                                                  \
188         p_v -= i_chroma_width;                                                  \
189     }                                                                           \
190                                                                                 \
191     /*                                                                          \
192      * Handle vertical scaling. The current line can be copied or next one      \
193      * can be ignored.                                                          \
194      */                                                                         \
195     switch( i_vertical_scaling )                                                \
196     {                                                                           \
197     case -1:                             /* vertical scaling factor is < 1 */   \
198         while( (i_scale_count -= i_pic_height) >= 0 )                           \
199         {                                                                       \
200             /* Height reduction: skip next source line */                       \
201             p_y += i_width;                                                     \
202             i_y++;                                                              \
203             if( (CHROMA == 420) || (CHROMA == 422) )                            \
204             {                                                                   \
205                 if( i_y & 0x1 )                                                 \
206                 {                                                               \
207                     p_u += i_chroma_width;                                      \
208                     p_v += i_chroma_width;                                      \
209                 }                                                               \
210             }                                                                   \
211             else if( CHROMA == 444 )                                            \
212             {                                                                   \
213                 p_u += i_width;                                                 \
214                 p_v += i_width;                                                 \
215             }                                                                   \
216         }                                                                       \
217         i_scale_count += i_height;                                              \
218         break;                                                                  \
219     case 1:                              /* vertical scaling factor is > 1 */   \
220         while( (i_scale_count -= i_height) > 0 )                                \
221         {                                                                       \
222             /* Height increment: copy previous picture line */                  \
223             for( i_x = i_pic_width / 16; i_x--; )                               \
224             {                                                                   \
225                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );             \
226                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );             \
227                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );             \
228                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );             \
229             }                                                                   \
230             p_pic +=        i_pic_line_width;                                   \
231             p_pic_start +=  i_pic_line_width;                                   \
232         }                                                                       \
233         i_scale_count += i_pic_height;                                          \
234         break;                                                                  \
235     }                                                                           \
236
237 /*******************************************************************************
238  * vout_InitYUV: allocate and initialize translations tables
239  *******************************************************************************
240  * This function will allocate memory to store translation tables, depending
241  * of the screen depth.
242  *******************************************************************************/
243 int vout_InitYUV( vout_thread_t *p_vout )
244 {
245     size_t      tables_size;                          /* tables size, in bytes */
246     
247     /* Computes tables size */
248     switch( p_vout->i_screen_depth )
249     {
250     case 15:
251     case 16:
252         tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
253         break;        
254     case 24:        
255     case 32:
256 #ifndef DEBUG
257     default:        
258 #endif
259         tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);        
260         break;        
261 #ifdef DEBUG
262     default:
263         intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
264         tables_size = 0;
265         break;        
266 #endif      
267     }
268     
269     /* Allocate memory */
270     p_vout->yuv.p_base = malloc( tables_size );
271     if( p_vout->yuv.p_base == NULL )
272     {
273         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
274         return( 1 );                
275     }
276
277     /* Allocate memory for convertion buffer and offset array */
278     p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
279     if( p_vout->yuv.p_buffer == NULL )
280     {
281         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
282         free( p_vout->yuv.p_base );
283         return( 1 );                
284     }
285     p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );    
286     if( p_vout->yuv.p_offset == NULL )
287     {
288         intf_ErrMsg("error: %s\n", strerror(ENOMEM));
289         free( p_vout->yuv.p_base );
290         free( p_vout->yuv.p_buffer );        
291         return( 1 );                
292     }
293
294     /* Initialize tables */
295     SetYUV( p_vout );
296     return( 0 );    
297 }
298
299 /*******************************************************************************
300  * vout_ResetTables: re-initialize translations tables
301  *******************************************************************************
302  * This function will initialize the tables allocated by vout_CreateTables and
303  * set functions pointers.
304  *******************************************************************************/
305 int vout_ResetYUV( vout_thread_t *p_vout )
306 {
307     vout_EndYUV( p_vout );    
308     return( vout_InitYUV( p_vout ) );    
309 }
310
311 /*******************************************************************************
312  * vout_EndYUV: destroy translations tables
313  *******************************************************************************
314  * Free memory allocated by vout_CreateTables.
315  *******************************************************************************/
316 void vout_EndYUV( vout_thread_t *p_vout )
317 {
318     free( p_vout->yuv.p_base );
319     free( p_vout->yuv.p_buffer );
320     free( p_vout->yuv.p_offset );    
321 }
322
323 /* following functions are local */
324
325 /*******************************************************************************
326  * BinaryLog: computes the base 2 log of a binary value
327  *******************************************************************************
328  * This functions is used by MaskToShift during tables initialisation, to
329  * get a bit index from a binary value.
330  *******************************************************************************/
331 static int BinaryLog(u32 i)
332 {
333     int i_log;
334
335     i_log = 0;
336     if (i & 0xffff0000) 
337     {        
338         i_log = 16;
339     }    
340     if (i & 0xff00ff00) 
341     {        
342         i_log += 8;
343     }    
344     if (i & 0xf0f0f0f0) 
345     {        
346         i_log += 4;
347     }    
348     if (i & 0xcccccccc) 
349     {        
350         i_log += 2;
351     }    
352     if (i & 0xaaaaaaaa) 
353     {        
354         i_log++;
355     }    
356     if (i != ((u32)1 << i_log))
357     {        
358         intf_ErrMsg("internal error: binary log overflow\n");        
359     }    
360
361     return( i_log );
362 }
363
364 /*******************************************************************************
365  * MaskToShift: Transform a color mask into right and left shifts
366  *******************************************************************************
367  * This function is used during table initialisation. It can return a value
368  *******************************************************************************/
369 static void MaskToShift (int *pi_right, int *pi_left, u32 i_mask)
370 {
371     u32 i_low, i_high;                   /* lower hand higher bits of the mask */
372
373     /* Get bits */
374     i_low =  i_mask & (- i_mask);                     /* lower bit of the mask */
375     i_high = i_mask + i_low;                         /* higher bit of the mask */
376
377     /* Transform bits into an index */
378     i_low =  BinaryLog (i_low);
379     i_high = BinaryLog (i_high);
380
381     /* Update pointers and return */
382     *pi_left =   i_low;
383     *pi_right = (8 - i_high + i_low);
384 }
385
386 /*******************************************************************************
387  * SetGammaTable: return intensity table transformed by gamma curve.
388  *******************************************************************************
389  * pi_table is a table of 256 entries from 0 to 255.
390  *******************************************************************************/
391 static void SetGammaTable( int *pi_table, double f_gamma )
392 {
393     int         i_y;                                         /* base intensity */
394
395     /* Use exp(gamma) instead of gamma */
396     f_gamma = exp(f_gamma );
397
398     /* Build gamma table */
399     for( i_y = 0; i_y < 256; i_y++ )
400     {
401         pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
402     }
403  }
404
405 /*******************************************************************************
406  * SetYUV: compute tables and set function pointers
407 + *******************************************************************************/
408 static void SetYUV( vout_thread_t *p_vout )
409 {
410     int         pi_gamma[256];                                  /* gamma table */    
411     int         i_index;                                    /* index in tables */
412     int         i_red_right, i_red_left;                         /* red shifts */
413     int         i_green_right, i_green_left;                   /* green shifts */
414     int         i_blue_right, i_blue_left;                      /* blue shifts */
415
416     /* Build gamma table */    
417     SetGammaTable( pi_gamma, p_vout->f_gamma );
418     
419     /*          
420      * Set color masks and shifts
421      */
422     switch( p_vout->i_screen_depth )
423     {
424     case 15:
425         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
426         MaskToShift( &i_green_right, &i_green_left, 0x03e0 );
427         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );        
428         break;        
429     case 16:
430         MaskToShift( &i_red_right,   &i_red_left,   0xf800 );
431         MaskToShift( &i_green_right, &i_green_left, 0x07e0 );
432         MaskToShift( &i_blue_right,  &i_blue_left,  0x001f );
433         break;        
434     case 24:
435     case 32:        
436         MaskToShift( &i_red_right,   &i_red_left,   0x00ff0000 );
437         MaskToShift( &i_green_right, &i_green_left, 0x0000ff00 );
438         MaskToShift( &i_blue_right,  &i_blue_left,  0x000000ff );
439         break;
440 #ifdef DEBUG
441     default:
442         intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
443         break;        
444 #endif      
445     }
446
447     /*
448      * Set pointers and build YUV tables
449      */        
450     if( p_vout->b_grayscale )
451     {
452         /* Grayscale: build gray table */
453         switch( p_vout->i_screen_depth )
454         {
455         case 15:
456         case 16:         
457             p_vout->yuv.yuv.p_gray16 =  (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
458             for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
459             {
460                 p_vout->yuv.yuv.p_gray16[ -i_index ] = 
461                     ((pi_gamma[ 0 ] >> i_red_right)   << i_red_left)   |
462                     ((pi_gamma[ 0 ] >> i_green_right) << i_green_left) |
463                     ((pi_gamma[ 0 ] >> i_blue_right)  << i_blue_left);
464                 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = 
465                     ((pi_gamma[ 255 ] >> i_red_right)   << i_red_left)   |
466                     ((pi_gamma[ 255 ] >> i_green_right) << i_green_left) |
467                     ((pi_gamma[ 255 ] >> i_blue_right)  << i_blue_left);
468             }            
469             for( i_index = 0; i_index < 256; i_index++) 
470             {
471                 p_vout->yuv.yuv.p_gray16[ i_index ] = 
472                     ((pi_gamma[ i_index ] >> i_red_right)   << i_red_left)   |
473                     ((pi_gamma[ i_index ] >> i_green_right) << i_green_left) |
474                     ((pi_gamma[ i_index ] >> i_blue_right)  << i_blue_left);
475             }
476             break;        
477         case 24:
478         case 32:        
479             p_vout->yuv.yuv.p_gray32 =  (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
480             for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
481             {
482                 p_vout->yuv.yuv.p_gray32[ -i_index ] = 
483                     ((pi_gamma[ 0 ] >> i_red_right)   << i_red_left)   |
484                     ((pi_gamma[ 0 ] >> i_green_right) << i_green_left) |
485                     ((pi_gamma[ 0 ] >> i_blue_right)  << i_blue_left);
486                 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = 
487                     ((pi_gamma[ 255 ] >> i_red_right)   << i_red_left)   |
488                     ((pi_gamma[ 255 ] >> i_green_right) << i_green_left) |
489                     ((pi_gamma[ 255 ] >> i_blue_right)  << i_blue_left);
490             }            
491             for( i_index = 0; i_index < 256; i_index++) 
492             {
493                 p_vout->yuv.yuv.p_gray32[ i_index ] = 
494                     ((pi_gamma[ i_index ] >> i_red_right)   << i_red_left)   |
495                     ((pi_gamma[ i_index ] >> i_green_right) << i_green_left) |
496                     ((pi_gamma[ i_index ] >> i_blue_right)  << i_blue_left);
497             }
498             break;        
499          }
500     }
501     else
502     {
503         /* Color: build red, green and blue tables */
504         switch( p_vout->i_screen_depth )
505         {
506         case 15:
507         case 16:            
508             p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
509             for( i_index = 0; i_index < RED_MARGIN; i_index++ )
510             {
511                 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
512                 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;                
513             }
514             for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
515             {
516                 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right)<<i_green_left;
517                 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
518             }
519             for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
520             {
521                 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
522                 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;                
523             }
524             for( i_index = 0; i_index < 256; i_index++ )
525             {
526                 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
527                 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
528                 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
529             }            
530             break;        
531         case 24:
532         case 32:
533             p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
534             for( i_index = 0; i_index < RED_MARGIN; i_index++ )
535             {
536                 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
537                 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;                
538             }
539             for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
540             {
541                 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right)<<i_green_left;
542                 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
543             }
544             for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
545             {
546                 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
547                 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;                
548             }
549             for( i_index = 0; i_index < 256; i_index++ )
550             {
551                 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
552                 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
553                 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
554             }            
555             break;        
556         }
557     }    
558
559     /*
560      * Set functions pointers
561      */
562     if( p_vout->b_grayscale )
563     {
564         /* Grayscale */
565         switch( p_vout->i_screen_depth )
566         {
567         case 15:
568         case 16:  
569             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;        
570             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;        
571             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;        
572             break;        
573         case 24:
574             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;        
575             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;        
576             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;        
577             break;        
578         case 32:        
579             p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;        
580             p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;        
581             p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;        
582             break;        
583         }        
584     }
585     else
586     {
587         /* Color */
588         switch( p_vout->i_screen_depth )
589         {
590         case 15:
591         case 16:  
592             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB16;        
593             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB16;        
594             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB16;        
595             break;        
596         case 24:
597             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB24;        
598             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB24;        
599             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB24;        
600             break;        
601         case 32:        
602             p_vout->yuv.p_Convert420 =   (vout_yuv_convert_t *) ConvertYUV420RGB32;        
603             p_vout->yuv.p_Convert422 =   (vout_yuv_convert_t *) ConvertYUV422RGB32;        
604             p_vout->yuv.p_Convert444 =   (vout_yuv_convert_t *) ConvertYUV444RGB32;        
605             break;        
606         }
607     }        
608 }
609
610 /*******************************************************************************
611  * SetOffset: build offset array for convertion functions
612  *******************************************************************************
613  * This function will build an offset array used in later convertion functions.
614  * It will also set horizontal and vertical scaling indicators.
615  *******************************************************************************/
616 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height, 
617                        boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
618 {    
619     int i_x;                                      /* x position in destination */
620     int i_scale_count;                                       /* modulo counter */
621
622     /*
623      * Prepare horizontal offset array
624      */      
625     if( i_pic_width - i_width > 0 )
626     {
627         /* Prepare scaling array for horizontal extension */
628         *pb_h_scaling =  1;   
629         i_scale_count =         i_pic_width;
630         for( i_x = i_width; i_x--; )
631         {
632             while( (i_scale_count -= i_width) > 0 )
633             {
634                 *p_offset++ = 0;                
635             }
636             *p_offset++ = 1;            
637             i_scale_count += i_pic_width;            
638         }        
639     }
640     else if( i_pic_width - i_width < 0 )
641     {
642         /* Prepare scaling array for horizontal reduction */
643         *pb_h_scaling =  1;
644         i_scale_count =         i_pic_width;
645         for( i_x = i_pic_width; i_x--; )
646         {
647             *p_offset = 1;            
648             while( (i_scale_count -= i_pic_width) >= 0 )
649             {                
650                 *p_offset += 1;                
651             }
652             p_offset++;
653             i_scale_count += i_width;
654         }        
655     }
656     else
657     {
658         /* No horizontal scaling: YUV convertion is done directly to picture */          
659         *pb_h_scaling = 0;        
660     }
661
662     /*
663      * Set vertical scaling indicator
664      */
665     if( i_pic_height - i_height > 0 )
666     {
667         *pi_v_scaling = 1;        
668     }
669     else if( i_pic_height - i_height < 0 )
670     {
671         *pi_v_scaling = -1;        
672     }
673     else
674     {
675         *pi_v_scaling = 0;        
676     }
677 }
678
679 /*******************************************************************************
680  * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 15 or 16 bpp
681  *******************************************************************************/
682 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,
683                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
684                              int i_matrix_coefficients )
685 {
686     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
687     int         i_vertical_scaling;                   /* vertical scaling type */
688     int         i_x, i_y;                   /* horizontal and vertical indexes */
689     int         i_scale_count;                         /* scale modulo counter */
690     int         i_chroma_width;                      /* chroma width, not used */    
691     u16 *       p_gray;                               /* base convertion table */
692     u16 *       p_pic_start;         /* beginning of the current line for copy */
693     u16 *       p_buffer_start;                     /* convertion buffer start */
694     u16 *       p_buffer;                         /* convertion buffer pointer */
695     int *       p_offset_start;                          /* offset array start */
696     int *       p_offset;                              /* offset array pointer */    
697     
698     /* 
699      * Initialize some values  - i_pic_line_width will store the line skip 
700      */
701     i_pic_line_width -= i_pic_width;                                            
702     p_gray =            p_vout->yuv.yuv.p_gray16;    
703     p_buffer_start =    p_vout->yuv.p_buffer;                                   
704     p_offset_start =    p_vout->yuv.p_offset;                                   
705     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
706                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
707
708     /*
709      * Perform convertion
710      */
711     i_scale_count = i_pic_height;
712     for( i_y = 0; i_y < i_height; i_y++ )
713     {
714         /* Mark beginnning of line for possible later line copy, and initialize
715          * buffer */
716         p_pic_start =   p_pic;
717         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
718
719         /* Do YUV convertion to buffer - YUV picture is always formed of 16
720          * pixels wide blocks */
721         for( i_x = i_width / 16; i_x--;  )
722         {
723             *p_buffer++ = p_gray[ *p_y++ ];
724             *p_buffer++ = p_gray[ *p_y++ ];
725             *p_buffer++ = p_gray[ *p_y++ ];
726             *p_buffer++ = p_gray[ *p_y++ ];
727             *p_buffer++ = p_gray[ *p_y++ ];
728             *p_buffer++ = p_gray[ *p_y++ ];
729             *p_buffer++ = p_gray[ *p_y++ ];
730             *p_buffer++ = p_gray[ *p_y++ ];
731             *p_buffer++ = p_gray[ *p_y++ ];
732             *p_buffer++ = p_gray[ *p_y++ ];
733             *p_buffer++ = p_gray[ *p_y++ ];
734             *p_buffer++ = p_gray[ *p_y++ ];
735             *p_buffer++ = p_gray[ *p_y++ ];
736             *p_buffer++ = p_gray[ *p_y++ ];
737             *p_buffer++ = p_gray[ *p_y++ ];
738             *p_buffer++ = p_gray[ *p_y++ ];
739         }             
740
741         /* Do horizontal and vertical scaling */
742         SCALE_WIDTH;
743         SCALE_HEIGHT(400);        
744     }
745 }
746
747 /*******************************************************************************
748  * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 24 bpp
749  *******************************************************************************/
750 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,
751                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
752                              int i_matrix_coefficients )
753 {
754     //??
755 }
756
757 /*******************************************************************************
758  * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 32 bpp
759  *******************************************************************************/
760 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,
761                              int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
762                              int i_matrix_coefficients )
763 {
764     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
765     int         i_vertical_scaling;                   /* vertical scaling type */
766     int         i_x, i_y;                   /* horizontal and vertical indexes */
767     int         i_scale_count;                         /* scale modulo counter */
768     int         i_chroma_width;                      /* chroma width, not used */    
769     u32 *       p_gray;                               /* base convertion table */
770     u32 *       p_pic_start;         /* beginning of the current line for copy */
771     u32 *       p_buffer_start;                     /* convertion buffer start */
772     u32 *       p_buffer;                         /* convertion buffer pointer */
773     int *       p_offset_start;                          /* offset array start */
774     int *       p_offset;                              /* offset array pointer */    
775     
776     /* 
777      * Initialize some values  - i_pic_line_width will store the line skip 
778      */
779     i_pic_line_width -= i_pic_width;                                            
780     p_gray =            p_vout->yuv.yuv.p_gray32;    
781     p_buffer_start =    p_vout->yuv.p_buffer;                                   
782     p_offset_start =    p_vout->yuv.p_offset;                                   
783     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
784                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
785
786     /*
787      * Perform convertion
788      */
789     i_scale_count = i_pic_height;
790     for( i_y = 0; i_y < i_height; i_y++ )
791     {
792         /* Mark beginnning of line for possible later line copy, and initialize
793          * buffer */
794         p_pic_start =   p_pic;
795         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
796
797         /* Do YUV convertion to buffer - YUV picture is always formed of 16
798          * pixels wide blocks */
799         for( i_x = i_width / 16; i_x--;  )
800         {
801             *p_buffer++ = p_gray[ *p_y++ ];
802             *p_buffer++ = p_gray[ *p_y++ ];
803             *p_buffer++ = p_gray[ *p_y++ ];
804             *p_buffer++ = p_gray[ *p_y++ ];
805             *p_buffer++ = p_gray[ *p_y++ ];
806             *p_buffer++ = p_gray[ *p_y++ ];
807             *p_buffer++ = p_gray[ *p_y++ ];
808             *p_buffer++ = p_gray[ *p_y++ ];
809             *p_buffer++ = p_gray[ *p_y++ ];
810             *p_buffer++ = p_gray[ *p_y++ ];
811             *p_buffer++ = p_gray[ *p_y++ ];
812             *p_buffer++ = p_gray[ *p_y++ ];
813             *p_buffer++ = p_gray[ *p_y++ ];
814             *p_buffer++ = p_gray[ *p_y++ ];
815             *p_buffer++ = p_gray[ *p_y++ ];
816             *p_buffer++ = p_gray[ *p_y++ ];
817         }             
818
819         /* Do horizontal and vertical scaling */
820         SCALE_WIDTH;
821         SCALE_HEIGHT(400);        
822     }
823 }
824
825 /*******************************************************************************
826  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 15 or 16 bpp
827  *******************************************************************************/
828 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,
829                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
830                                 int i_matrix_coefficients )
831 {
832 /* MMX version */
833   //  int                 i_chroma_width, i_chroma_skip;      /* width and eol for chroma */
834 /*
835     i_chroma_width =    i_width / 2;
836     i_chroma_skip =     i_skip / 2;
837     ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height, 
838                            (i_width + i_skip) * sizeof( yuv_data_t ), 
839                            (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
840                            i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
841                            p_vout->i_screen_depth == 15 );    
842 */
843     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
844     int         i_vertical_scaling;                   /* vertical scaling type */
845     int         i_x, i_y;                   /* horizontal and vertical indexes */
846     int         i_scale_count;                         /* scale modulo counter */
847     int         i_uval, i_vval;                             /* U and V samples */
848     int         i_red, i_green, i_blue;            /* U and V modified samples */
849     int         i_chroma_width;                                /* chroma width */
850     u16 *       p_yuv;                                /* base convertion table */
851     u16 *       p_ybase;                       /* Y dependant convertion table */   
852     u16 *       p_pic_start;         /* beginning of the current line for copy */
853     u16 *       p_buffer_start;                     /* convertion buffer start */
854     u16 *       p_buffer;                         /* convertion buffer pointer */
855     int *       p_offset_start;                          /* offset array start */
856     int *       p_offset;                              /* offset array pointer */
857     
858     /* 
859      * Initialize some values  - i_pic_line_width will store the line skip 
860      */
861     i_pic_line_width -= i_pic_width;
862     i_chroma_width =    i_width / 2;
863     p_yuv =             p_vout->yuv.yuv.p_rgb16;
864     p_buffer_start =    p_vout->yuv.p_buffer;        
865     p_offset_start =    p_vout->yuv.p_offset;                    
866     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
867                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
868
869     /*
870      * Perform convertion
871      */
872     i_scale_count = i_pic_height;
873     for( i_y = 0; i_y < i_height; i_y++ )
874     {
875         /* Mark beginnning of line for possible later line copy, and initialize
876          * buffer */
877         p_pic_start =   p_pic;
878         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
879
880         /* Do YUV convertion to buffer - YUV picture is always formed of 16
881          * pixels wide blocks */
882         for( i_x = i_width / 16; i_x--;  )
883         {
884             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
885             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
886             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
887             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
888             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
889             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
890             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
891             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
892         }             
893
894         /* Do horizontal and vertical scaling */
895         SCALE_WIDTH;
896         SCALE_HEIGHT(420);        
897     }
898 }
899
900 /*******************************************************************************
901  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 15 or 16 bpp
902  *******************************************************************************/
903 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,
904                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
905                                 int i_matrix_coefficients )
906 {
907     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
908     int         i_vertical_scaling;                   /* vertical scaling type */
909     int         i_x, i_y;                   /* horizontal and vertical indexes */
910     int         i_scale_count;                         /* scale modulo counter */
911     int         i_uval, i_vval;                             /* U and V samples */
912     int         i_red, i_green, i_blue;            /* U and V modified samples */
913     int         i_chroma_width;                                /* chroma width */
914     u16 *       p_yuv;                                /* base convertion table */
915     u16 *       p_ybase;                       /* Y dependant convertion table */   
916     u16 *       p_pic_start;         /* beginning of the current line for copy */
917     u16 *       p_buffer_start;                     /* convertion buffer start */
918     u16 *       p_buffer;                         /* convertion buffer pointer */
919     int *       p_offset_start;                          /* offset array start */
920     int *       p_offset;                              /* offset array pointer */
921     
922     /* 
923      * Initialize some values  - i_pic_line_width will store the line skip 
924      */
925     i_pic_line_width -= i_pic_width;
926     i_chroma_width =    i_width / 2;
927     p_yuv =             p_vout->yuv.yuv.p_rgb16;
928     p_buffer_start =    p_vout->yuv.p_buffer;        
929     p_offset_start =    p_vout->yuv.p_offset;                    
930     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
931                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
932
933     /*
934      * Perform convertion
935      */
936     i_scale_count = i_pic_height;
937     for( i_y = 0; i_y < i_height; i_y++ )
938     {
939         /* Mark beginnning of line for possible later line copy, and initialize
940          * buffer */
941         p_pic_start =   p_pic;
942         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
943
944         /* Do YUV convertion to buffer - YUV picture is always formed of 16
945          * pixels wide blocks */
946         for( i_x = i_width / 16; i_x--;  )
947         {
948             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
949             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
950             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
951             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
952             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
953             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
954             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
955             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
956         }             
957
958         /* Do horizontal and vertical scaling */
959         SCALE_WIDTH;
960         SCALE_HEIGHT(422);        
961     }
962 }
963
964 /*******************************************************************************
965  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 15 or 16 bpp
966  *******************************************************************************/
967 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,
968                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
969                                 int i_matrix_coefficients )
970 {
971     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
972     int         i_vertical_scaling;                   /* vertical scaling type */
973     int         i_x, i_y;                   /* horizontal and vertical indexes */
974     int         i_scale_count;                         /* scale modulo counter */
975     int         i_uval, i_vval;                             /* U and V samples */
976     int         i_red, i_green, i_blue;            /* U and V modified samples */
977     int         i_chroma_width;                      /* chroma width, not used */
978     u16 *       p_yuv;                                /* base convertion table */
979     u16 *       p_ybase;                       /* Y dependant convertion table */   
980     u16 *       p_pic_start;         /* beginning of the current line for copy */
981     u16 *       p_buffer_start;                     /* convertion buffer start */
982     u16 *       p_buffer;                         /* convertion buffer pointer */
983     int *       p_offset_start;                          /* offset array start */
984     int *       p_offset;                              /* offset array pointer */
985     
986     /* 
987      * Initialize some values  - i_pic_line_width will store the line skip 
988      */
989     i_pic_line_width -= i_pic_width;
990     p_yuv =             p_vout->yuv.yuv.p_rgb16;
991     p_buffer_start =    p_vout->yuv.p_buffer;        
992     p_offset_start =    p_vout->yuv.p_offset;                    
993     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
994                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
995
996     /*
997      * Perform convertion
998      */
999     i_scale_count = i_pic_height;
1000     for( i_y = 0; i_y < i_height; i_y++ )
1001     {
1002         /* Mark beginnning of line for possible later line copy, and initialize
1003          * buffer */
1004         p_pic_start =   p_pic;
1005         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1006
1007         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1008          * pixels wide blocks */
1009         for( i_x = i_width / 16; i_x--;  )
1010         {
1011             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1012             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1013             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1014             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1015             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1016             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1017             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1018             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1019         }             
1020
1021         /* Do horizontal and vertical scaling */
1022         SCALE_WIDTH;
1023         SCALE_HEIGHT(444);        
1024     }
1025 }
1026
1027 /*******************************************************************************
1028  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 24 bpp
1029  *******************************************************************************/
1030 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,
1031                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1032                                 int i_matrix_coefficients )
1033 {
1034     //???
1035 }
1036
1037 /*******************************************************************************
1038  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 24 bpp
1039  *******************************************************************************/
1040 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,
1041                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1042                                 int i_matrix_coefficients )
1043 {
1044     //???
1045 }
1046
1047 /*******************************************************************************
1048  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 24 bpp
1049  *******************************************************************************/
1050 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,
1051                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1052                                 int i_matrix_coefficients )
1053 {    
1054     //???
1055 }
1056
1057 /*******************************************************************************
1058  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 32 bpp
1059  *******************************************************************************/
1060 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,
1061                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1062                                 int i_matrix_coefficients )
1063 {
1064     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
1065     int         i_vertical_scaling;                   /* vertical scaling type */
1066     int         i_x, i_y;                   /* horizontal and vertical indexes */
1067     int         i_scale_count;                         /* scale modulo counter */
1068     int         i_uval, i_vval;                             /* U and V samples */
1069     int         i_red, i_green, i_blue;            /* U and V modified samples */
1070     int         i_chroma_width;                                /* chroma width */
1071     u32 *       p_yuv;                                /* base convertion table */
1072     u32 *       p_ybase;                       /* Y dependant convertion table */   
1073     u32 *       p_pic_start;         /* beginning of the current line for copy */
1074     u32 *       p_buffer_start;                     /* convertion buffer start */
1075     u32 *       p_buffer;                         /* convertion buffer pointer */
1076     int *       p_offset_start;                          /* offset array start */
1077     int *       p_offset;                              /* offset array pointer */
1078     
1079     /* 
1080      * Initialize some values  - i_pic_line_width will store the line skip 
1081      */
1082     i_pic_line_width -= i_pic_width;
1083     i_chroma_width =    i_width / 2;
1084     p_yuv =             p_vout->yuv.yuv.p_rgb32;
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_Y_PIXEL;
1106             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1107             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1108             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1109             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1110             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1111             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1112             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1113         }             
1114
1115         /* Do horizontal and vertical scaling */
1116         SCALE_WIDTH;
1117         SCALE_HEIGHT(420);        
1118     }
1119 }
1120
1121 /*******************************************************************************
1122  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 32 bpp
1123  *******************************************************************************/
1124 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,
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     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
1129     int         i_vertical_scaling;                   /* vertical scaling type */
1130     int         i_x, i_y;                   /* horizontal and vertical indexes */
1131     int         i_scale_count;                         /* scale modulo counter */
1132     int         i_uval, i_vval;                             /* U and V samples */
1133     int         i_red, i_green, i_blue;            /* U and V modified samples */
1134     int         i_chroma_width;                                /* chroma width */
1135     u32 *       p_yuv;                                /* base convertion table */
1136     u32 *       p_ybase;                       /* Y dependant convertion table */   
1137     u32 *       p_pic_start;         /* beginning of the current line for copy */
1138     u32 *       p_buffer_start;                     /* convertion buffer start */
1139     u32 *       p_buffer;                         /* convertion buffer pointer */
1140     int *       p_offset_start;                          /* offset array start */
1141     int *       p_offset;                              /* offset array pointer */
1142     
1143     /* 
1144      * Initialize some values  - i_pic_line_width will store the line skip 
1145      */
1146     i_pic_line_width -= i_pic_width;
1147     i_chroma_width =    i_width / 2;
1148     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1149     p_buffer_start =    p_vout->yuv.p_buffer;        
1150     p_offset_start =    p_vout->yuv.p_offset;                    
1151     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1152                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1153
1154     /*
1155      * Perform convertion
1156      */
1157     i_scale_count = i_pic_height;
1158     for( i_y = 0; i_y < i_height; i_y++ )
1159     {
1160         /* Mark beginnning of line for possible later line copy, and initialize
1161          * buffer */
1162         p_pic_start =   p_pic;
1163         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1164
1165         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1166          * pixels wide blocks */
1167         for( i_x = i_width / 16; i_x--;  )
1168         {
1169             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1170             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1171             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1172             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1173             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1174             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1175             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1176             CONVERT_YUV_PIXEL;  CONVERT_Y_PIXEL;
1177         }             
1178
1179         /* Do horizontal and vertical scaling */
1180         SCALE_WIDTH;
1181         SCALE_HEIGHT(422);        
1182     }
1183 }
1184
1185 /*******************************************************************************
1186  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 32 bpp
1187  *******************************************************************************/
1188 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,
1189                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1190                                 int i_matrix_coefficients )
1191 {
1192     boolean_t   b_horizontal_scaling;               /* horizontal scaling type */
1193     int         i_vertical_scaling;                   /* vertical scaling type */
1194     int         i_x, i_y;                   /* horizontal and vertical indexes */
1195     int         i_scale_count;                         /* scale modulo counter */
1196     int         i_uval, i_vval;                             /* U and V samples */
1197     int         i_red, i_green, i_blue;            /* U and V modified samples */
1198     int         i_chroma_width;                      /* chroma width, not used */
1199     u32 *       p_yuv;                                /* base convertion table */
1200     u32 *       p_ybase;                       /* Y dependant convertion table */   
1201     u32 *       p_pic_start;         /* beginning of the current line for copy */
1202     u32 *       p_buffer_start;                     /* convertion buffer start */
1203     u32 *       p_buffer;                         /* convertion buffer pointer */
1204     int *       p_offset_start;                          /* offset array start */
1205     int *       p_offset;                              /* offset array pointer */
1206     
1207     /* 
1208      * Initialize some values  - i_pic_line_width will store the line skip 
1209      */
1210     i_pic_line_width -= i_pic_width;
1211     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1212     p_buffer_start =    p_vout->yuv.p_buffer;        
1213     p_offset_start =    p_vout->yuv.p_offset;                    
1214     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1215                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1216
1217     /*
1218      * Perform convertion
1219      */
1220     i_scale_count = i_pic_height;
1221     for( i_y = 0; i_y < i_height; i_y++ )
1222     {
1223         /* Mark beginnning of line for possible later line copy, and initialize
1224          * buffer */
1225         p_pic_start =   p_pic;
1226         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1227
1228         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1229          * pixels wide blocks */
1230         for( i_x = i_width / 16; i_x--;  )
1231         {
1232             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1233             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1234             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1235             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1236             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1237             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1238             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1239             CONVERT_YUV_PIXEL;  CONVERT_YUV_PIXEL;
1240         }             
1241
1242         /* Do horizontal and vertical scaling */
1243         SCALE_WIDTH;
1244         SCALE_HEIGHT(444);        
1245     }
1246 }
1247
1248 //-------------------- walken code follow ---------------------------------------
1249
1250 /*
1251  * YUV to RGB routines.
1252  *
1253  * these routines calculate r, g and b values from each pixel's y, u and v.
1254  * these r, g an b values are then passed thru a table lookup to take the
1255  * gamma curve into account and find the corresponding pixel value.
1256  *
1257  * the table must store more than 3*256 values because of the possibility
1258  * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1259  * values are in the following intervals :
1260  * -176 to 255+176 for red
1261  * -133 to 255+133 for green
1262  * -222 to 255+222 for blue
1263  *
1264  * If the input y,u,v values are right, the r,g,b results are not expected
1265  * to move out of the 0 to 255 interval but who knows what will happen in
1266  * real use...
1267  *
1268  * the red, green and blue conversion tables are stored in a single 1935-entry
1269  * array. The respective positions of each component in the array have been
1270  * calculated to minimize the cache interactions of the 3 tables.
1271  */
1272
1273 static void yuvToRgb24 (unsigned char * Y,
1274                         unsigned char * U, unsigned char * V,
1275                         char * dest, int table[1935], int width)
1276 {
1277     int i;
1278     int u;
1279     int v;
1280     int uvRed;
1281     int uvGreen;
1282     int uvBlue;
1283     int * tableY;
1284     int tmp24;
1285
1286     i = width >> 3;
1287     while (i--) {
1288         u = *(U++);
1289         v = *(V++);
1290         uvRed = (V_RED_COEF*v) >> SHIFT;
1291         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1292         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1293
1294         tableY = table + *(Y++);
1295         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1296                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1297                         uvGreen] |
1298                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1299         *(dest++) = tmp24;
1300         *(dest++) = tmp24 >> 8;
1301         *(dest++) = tmp24 >> 16;
1302
1303         tableY = table + *(Y++);
1304         tmp24 = (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         *(dest++) = tmp24;
1309         *(dest++) = tmp24 >> 8;
1310         *(dest++) = tmp24 >> 16;
1311
1312         u = *(U++);
1313         v = *(V++);
1314         uvRed = (V_RED_COEF*v) >> SHIFT;
1315         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1316         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1317
1318         tableY = table + *(Y++);
1319         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1320                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1321                         uvGreen] |
1322                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1323         *(dest++) = tmp24;
1324         *(dest++) = tmp24 >> 8;
1325         *(dest++) = tmp24 >> 16;
1326
1327         tableY = table + *(Y++);
1328         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1329                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1330                         uvGreen] |
1331                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1332         *(dest++) = tmp24;
1333         *(dest++) = tmp24 >> 8;
1334         *(dest++) = tmp24 >> 16;
1335
1336         u = *(U++);
1337         v = *(V++);
1338         uvRed = (V_RED_COEF*v) >> SHIFT;
1339         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1340         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1341
1342         tableY = table + *(Y++);
1343         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1344                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1345                         uvGreen] |
1346                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1347         *(dest++) = tmp24;
1348         *(dest++) = tmp24 >> 8;
1349         *(dest++) = tmp24 >> 16;
1350
1351         tableY = table + *(Y++);
1352         tmp24 = (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         *(dest++) = tmp24;
1357         *(dest++) = tmp24 >> 8;
1358         *(dest++) = tmp24 >> 16;
1359
1360         u = *(U++);
1361         v = *(V++);
1362         uvRed = (V_RED_COEF*v) >> SHIFT;
1363         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1364         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1365
1366         tableY = table + *(Y++);
1367         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1368                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1369                         uvGreen] |
1370                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1371         *(dest++) = tmp24;
1372         *(dest++) = tmp24 >> 8;
1373         *(dest++) = tmp24 >> 16;
1374
1375         tableY = table + *(Y++);
1376         tmp24 = (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         *(dest++) = tmp24;
1381         *(dest++) = tmp24 >> 8;
1382         *(dest++) = tmp24 >> 16;
1383     }
1384
1385     i = (width & 7) >> 1;
1386     while (i--) {
1387         u = *(U++);
1388         v = *(V++);
1389         uvRed = (V_RED_COEF*v) >> SHIFT;
1390         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1391         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1392
1393         tableY = table + *(Y++);
1394         tmp24 = (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         *(dest++) = tmp24;
1399         *(dest++) = tmp24 >> 8;
1400         *(dest++) = tmp24 >> 16;
1401
1402         tableY = table + *(Y++);
1403         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1404                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1405                         uvGreen] |
1406                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1407         *(dest++) = tmp24;
1408         *(dest++) = tmp24 >> 8;
1409         *(dest++) = tmp24 >> 16;
1410     }
1411
1412     if (width & 1) {
1413         u = *(U++);
1414         v = *(V++);
1415         uvRed = (V_RED_COEF*v) >> SHIFT;
1416         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1417         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1418
1419         tableY = table + *(Y++);
1420         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1421                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1422                         uvGreen] |
1423                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1424         *(dest++) = tmp24;
1425         *(dest++) = tmp24 >> 8;
1426         *(dest++) = tmp24 >> 16;
1427     }
1428 }
1429