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