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