]> git.sesse.net Git - vlc/blob - src/video_output/video_yuv.c
IMPORTANT:
[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 convertion tables - Margins are used in case a RGB
65  * RGB convertion would give a value outside the 0-255 range. Offsets have been
66  * calculated to avoid using the same cache line for 2 tables. Convertion 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 convertion blocks
145  *****************************************************************************
146  * These convertion routines are used by YUV convertion functions.
147  * Convertion are made from p_y, p_u, p_v, which are modified, to p_buffer,
148  * which is also modified.
149  *****************************************************************************/
150 #define CONVERT_Y_PIXEL( 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, convertion 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, convertion 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 convertion, 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 convertion 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 convertion functions
582  *****************************************************************************
583  * This function will build an offset array used in later convertion 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 convertion 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 convertion table */
663     u8 *        p_pic_start;       /* beginning of the current line for copy */
664     u8 *        p_buffer_start;                   /* convertion buffer start */
665     u8 *        p_buffer;                       /* convertion 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 convertion
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 convertion 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_gray[ *p_y++ ];
695             *p_buffer++ = p_gray[ *p_y++ ];
696             *p_buffer++ = p_gray[ *p_y++ ];
697             *p_buffer++ = p_gray[ *p_y++ ];
698             *p_buffer++ = p_gray[ *p_y++ ];
699             *p_buffer++ = p_gray[ *p_y++ ];
700             *p_buffer++ = p_gray[ *p_y++ ];
701             *p_buffer++ = p_gray[ *p_y++ ];
702             *p_buffer++ = p_gray[ *p_y++ ];
703             *p_buffer++ = p_gray[ *p_y++ ];
704             *p_buffer++ = p_gray[ *p_y++ ];
705             *p_buffer++ = p_gray[ *p_y++ ];
706             *p_buffer++ = p_gray[ *p_y++ ];
707             *p_buffer++ = p_gray[ *p_y++ ];
708             *p_buffer++ = p_gray[ *p_y++ ];
709             *p_buffer++ = p_gray[ *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 convertion table */
731     u16 *       p_pic_start;       /* beginning of the current line for copy */
732     u16 *       p_buffer_start;                   /* convertion buffer start */
733     u16 *       p_buffer;                       /* convertion 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 convertion
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 convertion 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 convertion table */
809     u32 *       p_pic_start;       /* beginning of the current line for copy */
810     u32 *       p_buffer_start;                   /* convertion buffer start */
811     u32 *       p_buffer;                       /* convertion 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 convertion
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 convertion 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 convertion table */
879     u8 *        p_ybase;                     /* Y dependant convertion table */
880     u8 *        p_pic_start;       /* beginning of the current line for copy */
881     u8 *        p_buffer_start;                   /* convertion buffer start */
882     u8 *        p_buffer;                       /* convertion buffer pointer */
883     int *       p_offset_start;                        /* offset array start */
884     int *       p_offset;                            /* offset array pointer */
885     
886     /* 
887      * Initialize some values  - i_pic_line_width will store the line skip 
888      */
889     i_pic_line_width -= i_pic_width;
890     i_chroma_width =    i_width / 2;
891     p_yuv =             p_vout->yuv.yuv.p_rgb8;
892     p_buffer_start =    p_vout->yuv.p_buffer;        
893     p_offset_start =    p_vout->yuv.p_offset;                    
894     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
895                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
896
897     /*
898      * Perform convertion
899      */
900     i_scale_count = i_pic_height;
901     for( i_y = 0; i_y < i_height; i_y++ )
902     {
903         /* Mark beginnning of line for possible later line copy, and initialize
904          * buffer */
905         p_pic_start =   p_pic;
906         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
907
908         /* Do YUV convertion to buffer - YUV picture is always formed of 16
909          * pixels wide blocks */
910         for( i_x = i_width / 16; i_x--;  )
911         {
912             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
913             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
914             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
915             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
916             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
917             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
918             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
919             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
920         }             
921
922         /* Do horizontal and vertical scaling */
923         SCALE_WIDTH;
924         SCALE_HEIGHT(420, 1);        
925     }
926 }
927
928 /*****************************************************************************
929  * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
930  *****************************************************************************/
931 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,
932                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
933                                 int i_matrix_coefficients )
934 {
935     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
936     int         i_vertical_scaling;                 /* vertical scaling type */
937     int         i_x, i_y;                 /* horizontal and vertical indexes */
938     int         i_scale_count;                       /* scale modulo counter */
939     int         i_uval, i_vval;                           /* U and V samples */
940     int         i_red, i_green, i_blue;          /* U and V modified samples */
941     int         i_chroma_width;                              /* chroma width */
942     u8 *        p_yuv;                              /* base convertion table */
943     u8 *        p_ybase;                     /* Y dependant convertion table */
944     u8 *        p_pic_start;       /* beginning of the current line for copy */
945     u8 *        p_buffer_start;                   /* convertion buffer start */
946     u8 *        p_buffer;                       /* convertion buffer pointer */
947     int *       p_offset_start;                        /* offset array start */
948     int *       p_offset;                            /* offset array pointer */
949     
950     /* 
951      * Initialize some values  - i_pic_line_width will store the line skip 
952      */
953     i_pic_line_width -= i_pic_width;
954     i_chroma_width =    i_width / 2;
955     p_yuv =             p_vout->yuv.yuv.p_rgb8;
956     p_buffer_start =    p_vout->yuv.p_buffer;        
957     p_offset_start =    p_vout->yuv.p_offset;                    
958     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
959                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
960
961     /*
962      * Perform convertion
963      */
964     i_scale_count = i_pic_height;
965     for( i_y = 0; i_y < i_height; i_y++ )
966     {
967         /* Mark beginnning of line for possible later line copy, and initialize
968          * buffer */
969         p_pic_start =   p_pic;
970         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
971
972         /* Do YUV convertion to buffer - YUV picture is always formed of 16
973          * pixels wide blocks */
974         for( i_x = i_width / 16; i_x--;  )
975         {
976             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
977             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
978             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
979             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
980             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
981             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
982             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
983             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
984         }             
985
986         /* Do horizontal and vertical scaling */
987         SCALE_WIDTH;
988         SCALE_HEIGHT(422, 1);        
989     }
990 }
991
992 /*****************************************************************************
993  * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
994  *****************************************************************************/
995 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,
996                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
997                                 int i_matrix_coefficients )
998 {
999     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1000     int         i_vertical_scaling;                 /* vertical scaling type */
1001     int         i_x, i_y;                 /* horizontal and vertical indexes */
1002     int         i_scale_count;                       /* scale modulo counter */
1003     int         i_uval, i_vval;                           /* U and V samples */
1004     int         i_red, i_green, i_blue;          /* U and V modified samples */
1005     int         i_chroma_width;                    /* chroma width, not used */
1006     u8 *        p_yuv;                              /* base convertion table */
1007     u8 *        p_ybase;                     /* Y dependant convertion table */
1008     u8 *        p_pic_start;       /* beginning of the current line for copy */
1009     u8 *        p_buffer_start;                   /* convertion buffer start */
1010     u8 *        p_buffer;                       /* convertion buffer pointer */
1011     int *       p_offset_start;                        /* offset array start */
1012     int *       p_offset;                            /* offset array pointer */
1013     
1014     /* 
1015      * Initialize some values  - i_pic_line_width will store the line skip 
1016      */
1017     i_pic_line_width -= i_pic_width;
1018     p_yuv =             p_vout->yuv.yuv.p_rgb8;
1019     p_buffer_start =    p_vout->yuv.p_buffer;        
1020     p_offset_start =    p_vout->yuv.p_offset;                    
1021     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1022                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1023
1024     /*
1025      * Perform convertion
1026      */
1027     i_scale_count = i_pic_height;
1028     for( i_y = 0; i_y < i_height; i_y++ )
1029     {
1030         /* Mark beginnning of line for possible later line copy, and initialize
1031          * buffer */
1032         p_pic_start =   p_pic;
1033         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1034
1035         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1036          * pixels wide blocks */
1037         for( i_x = i_width / 16; i_x--;  )
1038         {
1039             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1040             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1041             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1042             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1043             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1044             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1045             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1046             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1047         }             
1048
1049         /* Do horizontal and vertical scaling */
1050         SCALE_WIDTH;
1051         SCALE_HEIGHT(444, 1);        
1052     }
1053 }
1054
1055 /*****************************************************************************
1056  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1057  *****************************************************************************/
1058 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,
1059                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1060                                 int i_matrix_coefficients )
1061 {
1062 /* MMX version */
1063   //  int                 i_chroma_width, i_chroma_skip;      /* width and eol for chroma */
1064 /*
1065     i_chroma_width =    i_width / 2;
1066     i_chroma_skip =     i_skip / 2;
1067     ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height, 
1068                            (i_width + i_skip) * sizeof( yuv_data_t ), 
1069                            (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1070                            i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1071                            p_vout->i_screen_depth == 15 );    
1072 */
1073     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1074     int         i_vertical_scaling;                 /* vertical scaling type */
1075     int         i_x, i_y;                 /* horizontal and vertical indexes */
1076     int         i_scale_count;                       /* scale modulo counter */
1077     int         i_uval, i_vval;                           /* U and V samples */
1078     int         i_red, i_green, i_blue;          /* U and V modified samples */
1079     int         i_chroma_width;                              /* chroma width */
1080     u16 *       p_yuv;                              /* base convertion table */
1081     u16 *       p_ybase;                     /* Y dependant convertion table */
1082     u16 *       p_pic_start;       /* beginning of the current line for copy */
1083     u16 *       p_buffer_start;                   /* convertion buffer start */
1084     u16 *       p_buffer;                       /* convertion buffer pointer */
1085     int *       p_offset_start;                        /* offset array start */
1086     int *       p_offset;                            /* offset array pointer */
1087     
1088     /* 
1089      * Initialize some values  - i_pic_line_width will store the line skip 
1090      */
1091     i_pic_line_width -= i_pic_width;
1092     i_chroma_width =    i_width / 2;
1093     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1094     p_buffer_start =    p_vout->yuv.p_buffer;        
1095     p_offset_start =    p_vout->yuv.p_offset;                    
1096     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1097                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1098
1099     /*
1100      * Perform convertion
1101      */
1102     i_scale_count = i_pic_height;
1103     for( i_y = 0; i_y < i_height; i_y++ )
1104     {
1105         /* Mark beginnning of line for possible later line copy, and initialize
1106          * buffer */
1107         p_pic_start =   p_pic;
1108         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1109
1110         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1111          * pixels wide blocks */
1112         for( i_x = i_width / 16; i_x--;  )
1113         {
1114             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1115             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1116             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1117             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1118             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1119             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1120             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1121             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1122         }             
1123
1124         /* Do horizontal and vertical scaling */
1125         SCALE_WIDTH;
1126         SCALE_HEIGHT(420, 2);        
1127     }
1128 }
1129
1130 /*****************************************************************************
1131  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1132  *****************************************************************************/
1133 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,
1134                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1135                                 int i_matrix_coefficients )
1136 {
1137     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1138     int         i_vertical_scaling;                 /* vertical scaling type */
1139     int         i_x, i_y;                 /* horizontal and vertical indexes */
1140     int         i_scale_count;                       /* scale modulo counter */
1141     int         i_uval, i_vval;                           /* U and V samples */
1142     int         i_red, i_green, i_blue;          /* U and V modified samples */
1143     int         i_chroma_width;                              /* chroma width */
1144     u16 *       p_yuv;                              /* base convertion table */
1145     u16 *       p_ybase;                     /* Y dependant convertion table */
1146     u16 *       p_pic_start;       /* beginning of the current line for copy */
1147     u16 *       p_buffer_start;                   /* convertion buffer start */
1148     u16 *       p_buffer;                       /* convertion buffer pointer */
1149     int *       p_offset_start;                        /* offset array start */
1150     int *       p_offset;                            /* offset array pointer */
1151     
1152     /* 
1153      * Initialize some values  - i_pic_line_width will store the line skip 
1154      */
1155     i_pic_line_width -= i_pic_width;
1156     i_chroma_width =    i_width / 2;
1157     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1158     p_buffer_start =    p_vout->yuv.p_buffer;        
1159     p_offset_start =    p_vout->yuv.p_offset;                    
1160     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1161                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1162
1163     /*
1164      * Perform convertion
1165      */
1166     i_scale_count = i_pic_height;
1167     for( i_y = 0; i_y < i_height; i_y++ )
1168     {
1169         /* Mark beginnning of line for possible later line copy, and initialize
1170          * buffer */
1171         p_pic_start =   p_pic;
1172         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1173
1174         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1175          * pixels wide blocks */
1176         for( i_x = i_width / 16; i_x--;  )
1177         {
1178             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1179             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1180             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1181             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1182             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1183             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1184             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1185             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1186         }             
1187
1188         /* Do horizontal and vertical scaling */
1189         SCALE_WIDTH;
1190         SCALE_HEIGHT(422, 2);        
1191     }
1192 }
1193
1194 /*****************************************************************************
1195  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1196  *****************************************************************************/
1197 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,
1198                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1199                                 int i_matrix_coefficients )
1200 {
1201     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1202     int         i_vertical_scaling;                 /* vertical scaling type */
1203     int         i_x, i_y;                 /* horizontal and vertical indexes */
1204     int         i_scale_count;                       /* scale modulo counter */
1205     int         i_uval, i_vval;                           /* U and V samples */
1206     int         i_red, i_green, i_blue;          /* U and V modified samples */
1207     int         i_chroma_width;                    /* chroma width, not used */
1208     u16 *       p_yuv;                              /* base convertion table */
1209     u16 *       p_ybase;                     /* Y dependant convertion table */
1210     u16 *       p_pic_start;       /* beginning of the current line for copy */
1211     u16 *       p_buffer_start;                   /* convertion buffer start */
1212     u16 *       p_buffer;                       /* convertion buffer pointer */
1213     int *       p_offset_start;                        /* offset array start */
1214     int *       p_offset;                            /* offset array pointer */
1215     
1216     /* 
1217      * Initialize some values  - i_pic_line_width will store the line skip 
1218      */
1219     i_pic_line_width -= i_pic_width;
1220     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1221     p_buffer_start =    p_vout->yuv.p_buffer;        
1222     p_offset_start =    p_vout->yuv.p_offset;                    
1223     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1224                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1225
1226     /*
1227      * Perform convertion
1228      */
1229     i_scale_count = i_pic_height;
1230     for( i_y = 0; i_y < i_height; i_y++ )
1231     {
1232         /* Mark beginnning of line for possible later line copy, and initialize
1233          * buffer */
1234         p_pic_start =   p_pic;
1235         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1236
1237         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1238          * pixels wide blocks */
1239         for( i_x = i_width / 16; i_x--;  )
1240         {
1241             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1242             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1243             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1244             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1245             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1246             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1247             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1248             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1249         }             
1250
1251         /* Do horizontal and vertical scaling */
1252         SCALE_WIDTH;
1253         SCALE_HEIGHT(444, 2);        
1254     }
1255 }
1256
1257 /*****************************************************************************
1258  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1259  *****************************************************************************/
1260 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,
1261                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1262                                 int i_matrix_coefficients )
1263 {
1264     //???
1265 }
1266
1267 /*****************************************************************************
1268  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1269  *****************************************************************************/
1270 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,
1271                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1272                                 int i_matrix_coefficients )
1273 {
1274     //???
1275 }
1276
1277 /*****************************************************************************
1278  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1279  *****************************************************************************/
1280 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,
1281                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1282                                 int i_matrix_coefficients )
1283 {    
1284     //???
1285 }
1286
1287 /*****************************************************************************
1288  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1289  *****************************************************************************/
1290 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,
1291                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1292                                 int i_matrix_coefficients )
1293 {
1294     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1295     int         i_vertical_scaling;                 /* vertical scaling type */
1296     int         i_x, i_y;                 /* horizontal and vertical indexes */
1297     int         i_scale_count;                       /* scale modulo counter */
1298     int         i_uval, i_vval;                           /* U and V samples */
1299     int         i_red, i_green, i_blue;          /* U and V modified samples */
1300     int         i_chroma_width;                              /* chroma width */
1301     u32 *       p_yuv;                              /* base convertion table */
1302     u32 *       p_ybase;                     /* Y dependant convertion table */
1303     u32 *       p_pic_start;       /* beginning of the current line for copy */
1304     u32 *       p_buffer_start;                   /* convertion buffer start */
1305     u32 *       p_buffer;                       /* convertion buffer pointer */
1306     int *       p_offset_start;                        /* offset array start */
1307     int *       p_offset;                            /* offset array pointer */
1308     
1309     /* 
1310      * Initialize some values  - i_pic_line_width will store the line skip 
1311      */
1312     i_pic_line_width -= i_pic_width;
1313     i_chroma_width =    i_width / 2;
1314     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1315     p_buffer_start =    p_vout->yuv.p_buffer;        
1316     p_offset_start =    p_vout->yuv.p_offset;                    
1317     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1318                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1319
1320     /*
1321      * Perform convertion
1322      */
1323     i_scale_count = i_pic_height;
1324     for( i_y = 0; i_y < i_height; i_y++ )
1325     {
1326         /* Mark beginnning of line for possible later line copy, and initialize
1327          * buffer */
1328         p_pic_start =   p_pic;
1329         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1330
1331         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1332          * pixels wide blocks */
1333         for( i_x = i_width / 16; i_x--;  )
1334         {
1335             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1336             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1337             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1338             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1339             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1340             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1341             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1342             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1343         }             
1344
1345         /* Do horizontal and vertical scaling */
1346         SCALE_WIDTH;
1347         SCALE_HEIGHT(420, 4);        
1348     }
1349 }
1350
1351 /*****************************************************************************
1352  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1353  *****************************************************************************/
1354 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,
1355                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1356                                 int i_matrix_coefficients )
1357 {
1358     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1359     int         i_vertical_scaling;                 /* vertical scaling type */
1360     int         i_x, i_y;                 /* horizontal and vertical indexes */
1361     int         i_scale_count;                       /* scale modulo counter */
1362     int         i_uval, i_vval;                           /* U and V samples */
1363     int         i_red, i_green, i_blue;          /* U and V modified samples */
1364     int         i_chroma_width;                              /* chroma width */
1365     u32 *       p_yuv;                              /* base convertion table */
1366     u32 *       p_ybase;                     /* Y dependant convertion table */
1367     u32 *       p_pic_start;       /* beginning of the current line for copy */
1368     u32 *       p_buffer_start;                   /* convertion buffer start */
1369     u32 *       p_buffer;                       /* convertion buffer pointer */
1370     int *       p_offset_start;                        /* offset array start */
1371     int *       p_offset;                            /* offset array pointer */
1372     
1373     /* 
1374      * Initialize some values  - i_pic_line_width will store the line skip 
1375      */
1376     i_pic_line_width -= i_pic_width;
1377     i_chroma_width =    i_width / 2;
1378     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1379     p_buffer_start =    p_vout->yuv.p_buffer;        
1380     p_offset_start =    p_vout->yuv.p_offset;                    
1381     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1382                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1383
1384     /*
1385      * Perform convertion
1386      */
1387     i_scale_count = i_pic_height;
1388     for( i_y = 0; i_y < i_height; i_y++ )
1389     {
1390         /* Mark beginnning of line for possible later line copy, and initialize
1391          * buffer */
1392         p_pic_start =   p_pic;
1393         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1394
1395         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1396          * pixels wide blocks */
1397         for( i_x = i_width / 16; i_x--;  )
1398         {
1399             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1400             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1401             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1402             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1403             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1404             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1405             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1406             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1407         }             
1408
1409         /* Do horizontal and vertical scaling */
1410         SCALE_WIDTH;
1411         SCALE_HEIGHT(422, 4);        
1412     }
1413 }
1414
1415 /*****************************************************************************
1416  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1417  *****************************************************************************/
1418 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,
1419                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1420                                 int i_matrix_coefficients )
1421 {
1422     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1423     int         i_vertical_scaling;                 /* vertical scaling type */
1424     int         i_x, i_y;                 /* horizontal and vertical indexes */
1425     int         i_scale_count;                       /* scale modulo counter */
1426     int         i_uval, i_vval;                           /* U and V samples */
1427     int         i_red, i_green, i_blue;          /* U and V modified samples */
1428     int         i_chroma_width;                    /* chroma width, not used */
1429     u32 *       p_yuv;                              /* base convertion table */
1430     u32 *       p_ybase;                     /* Y dependant convertion table */
1431     u32 *       p_pic_start;       /* beginning of the current line for copy */
1432     u32 *       p_buffer_start;                   /* convertion buffer start */
1433     u32 *       p_buffer;                       /* convertion buffer pointer */
1434     int *       p_offset_start;                        /* offset array start */
1435     int *       p_offset;                            /* offset array pointer */
1436     
1437     /* 
1438      * Initialize some values  - i_pic_line_width will store the line skip 
1439      */
1440     i_pic_line_width -= i_pic_width;
1441     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1442     p_buffer_start =    p_vout->yuv.p_buffer;        
1443     p_offset_start =    p_vout->yuv.p_offset;                    
1444     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
1445                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1446
1447     /*
1448      * Perform convertion
1449      */
1450     i_scale_count = i_pic_height;
1451     for( i_y = 0; i_y < i_height; i_y++ )
1452     {
1453         /* Mark beginnning of line for possible later line copy, and initialize
1454          * buffer */
1455         p_pic_start =   p_pic;
1456         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
1457
1458         /* Do YUV convertion to buffer - YUV picture is always formed of 16
1459          * pixels wide blocks */
1460         for( i_x = i_width / 16; i_x--;  )
1461         {
1462             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1463             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1464             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1465             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1466             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1467             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1468             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1469             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1470         }             
1471
1472         /* Do horizontal and vertical scaling */
1473         SCALE_WIDTH;
1474         SCALE_HEIGHT(444, 4);        
1475     }
1476 }
1477
1478 //-------------------- walken code follows ------------------------------------
1479
1480 /*
1481  * YUV to RGB routines.
1482  *
1483  * these routines calculate r, g and b values from each pixel's y, u and v.
1484  * these r, g an b values are then passed thru a table lookup to take the
1485  * gamma curve into account and find the corresponding pixel value.
1486  *
1487  * the table must store more than 3*256 values because of the possibility
1488  * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1489  * values are in the following intervals :
1490  * -176 to 255+176 for red
1491  * -133 to 255+133 for green
1492  * -222 to 255+222 for blue
1493  *
1494  * If the input y,u,v values are right, the r,g,b results are not expected
1495  * to move out of the 0 to 255 interval but who knows what will happen in
1496  * real use...
1497  *
1498  * the red, green and blue conversion tables are stored in a single 1935-entry
1499  * array. The respective positions of each component in the array have been
1500  * calculated to minimize the cache interactions of the 3 tables.
1501  */
1502
1503 #if 0
1504 //??
1505 static void yuvToRgb24 (unsigned char * Y,
1506                         unsigned char * U, unsigned char * V,
1507                         char * dest, int table[1935], int width)
1508 {
1509     int i;
1510     int u;
1511     int v;
1512     int uvRed;
1513     int uvGreen;
1514     int uvBlue;
1515     int * tableY;
1516     int tmp24;
1517
1518     i = width >> 3;
1519     while (i--) {
1520         u = *(U++);
1521         v = *(V++);
1522         uvRed = (V_RED_COEF*v) >> SHIFT;
1523         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1524         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1525
1526         tableY = table + *(Y++);
1527         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1528                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1529                         uvGreen] |
1530                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1531         *(dest++) = tmp24;
1532         *(dest++) = tmp24 >> 8;
1533         *(dest++) = tmp24 >> 16;
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         u = *(U++);
1545         v = *(V++);
1546         uvRed = (V_RED_COEF*v) >> SHIFT;
1547         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1548         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1549
1550         tableY = table + *(Y++);
1551         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1552                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1553                         uvGreen] |
1554                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1555         *(dest++) = tmp24;
1556         *(dest++) = tmp24 >> 8;
1557         *(dest++) = tmp24 >> 16;
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         u = *(U++);
1569         v = *(V++);
1570         uvRed = (V_RED_COEF*v) >> SHIFT;
1571         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1572         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1573
1574         tableY = table + *(Y++);
1575         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1576                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1577                         uvGreen] |
1578                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1579         *(dest++) = tmp24;
1580         *(dest++) = tmp24 >> 8;
1581         *(dest++) = tmp24 >> 16;
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         u = *(U++);
1593         v = *(V++);
1594         uvRed = (V_RED_COEF*v) >> SHIFT;
1595         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1596         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1597
1598         tableY = table + *(Y++);
1599         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1600                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1601                         uvGreen] |
1602                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1603         *(dest++) = tmp24;
1604         *(dest++) = tmp24 >> 8;
1605         *(dest++) = tmp24 >> 16;
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
1617     i = (width & 7) >> 1;
1618     while (i--) {
1619         u = *(U++);
1620         v = *(V++);
1621         uvRed = (V_RED_COEF*v) >> SHIFT;
1622         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1623         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1624
1625         tableY = table + *(Y++);
1626         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1627                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1628                         uvGreen] |
1629                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1630         *(dest++) = tmp24;
1631         *(dest++) = tmp24 >> 8;
1632         *(dest++) = tmp24 >> 16;
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
1644     if (width & 1) {
1645         u = *(U++);
1646         v = *(V++);
1647         uvRed = (V_RED_COEF*v) >> SHIFT;
1648         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1649         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1650
1651         tableY = table + *(Y++);
1652         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1653                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1654                         uvGreen] |
1655                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1656         *(dest++) = tmp24;
1657         *(dest++) = tmp24 >> 8;
1658         *(dest++) = tmp24 >> 16;
1659     }
1660 }
1661 #endif