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