]> git.sesse.net Git - vlc/blob - src/video_output/video_yuv.c
. am�lioration de la YUV 8bpp
[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     //??
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     //int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
1087     //int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
1088     //int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
1089     //int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
1090     //int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
1091     //int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
1092
1093     /*
1094      * Initialize some values  - i_pic_line_width will store the line skip
1095      */
1096     i_pic_line_width -= i_pic_width;
1097     i_chroma_width =    i_width / 2;
1098     p_offset_start =    p_vout->yuv.p_offset;
1099     p_lookup =          p_vout->yuv.p_base;
1100     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1101                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1102
1103     /*
1104      * Perform conversion
1105      */
1106     i_scale_count = i_pic_height;
1107     i_real_y = 0;
1108     for( i_y = 0; i_y < i_height; i_y++ )
1109     {
1110         /* Do horizontal and vertical scaling */
1111         SCALE_WIDTH_DITHER( 420 );
1112         SCALE_HEIGHT_DITHER( 420 );
1113     }
1114 }
1115
1116 /*****************************************************************************
1117  * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1118  *****************************************************************************/
1119 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,
1120                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1121                                 int i_matrix_coefficients )
1122 {
1123     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1124     int         i_vertical_scaling;                 /* vertical scaling type */
1125     int         i_x, i_y;                 /* horizontal and vertical indexes */
1126     int         i_scale_count;                       /* scale modulo counter */
1127     int         i_uval, i_vval;                           /* U and V samples */
1128     int         i_red, i_green, i_blue;          /* U and V modified samples */
1129     int         i_chroma_width;                              /* chroma width */
1130     u8 *        p_yuv;                              /* base conversion table */
1131     u8 *        p_ybase;                     /* Y dependant conversion table */
1132     u8 *        p_pic_start;       /* beginning of the current line for copy */
1133     u8 *        p_buffer_start;                   /* conversion buffer start */
1134     u8 *        p_buffer;                       /* conversion buffer pointer */
1135     int *       p_offset_start;                        /* offset array start */
1136     int *       p_offset;                            /* offset array pointer */
1137
1138     /*
1139      * Initialize some values  - i_pic_line_width will store the line skip
1140      */
1141     i_pic_line_width -= i_pic_width;
1142     i_chroma_width =    i_width / 2;
1143     p_yuv =             p_vout->yuv.yuv.p_rgb8;
1144     p_buffer_start =    p_vout->yuv.p_buffer;
1145     p_offset_start =    p_vout->yuv.p_offset;
1146     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1147                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1148
1149     /*
1150      * Perform conversion
1151      */
1152     i_scale_count = i_pic_height;
1153     for( i_y = 0; i_y < i_height; i_y++ )
1154     {
1155         /* Mark beginnning of line for possible later line copy, and initialize
1156          * buffer */
1157         p_pic_start =   p_pic;
1158         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1159
1160         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1161          * pixels wide blocks */
1162         for( i_x = i_width / 16; i_x--;  )
1163         {
1164             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
1165             CONVERT_YUV_PIXEL(1);  CONVERT_Y_PIXEL(1);
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         }
1173
1174         /* Do horizontal and vertical scaling */
1175         SCALE_WIDTH;
1176         SCALE_HEIGHT(422, 1);
1177     }
1178 }
1179
1180 /*****************************************************************************
1181  * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1182  *****************************************************************************/
1183 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,
1184                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1185                                 int i_matrix_coefficients )
1186 {
1187     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1188     int         i_vertical_scaling;                 /* vertical scaling type */
1189     int         i_x, i_y;                 /* horizontal and vertical indexes */
1190     int         i_scale_count;                       /* scale modulo counter */
1191     int         i_uval, i_vval;                           /* U and V samples */
1192     int         i_red, i_green, i_blue;          /* U and V modified samples */
1193     int         i_chroma_width;                    /* chroma width, not used */
1194     u8 *        p_yuv;                              /* base conversion table */
1195     u8 *        p_ybase;                     /* Y dependant conversion table */
1196     u8 *        p_pic_start;       /* beginning of the current line for copy */
1197     u8 *        p_buffer_start;                   /* conversion buffer start */
1198     u8 *        p_buffer;                       /* conversion buffer pointer */
1199     int *       p_offset_start;                        /* offset array start */
1200     int *       p_offset;                            /* offset array pointer */
1201
1202     /*
1203      * Initialize some values  - i_pic_line_width will store the line skip
1204      */
1205     i_pic_line_width -= i_pic_width;
1206     p_yuv =             p_vout->yuv.yuv.p_rgb8;
1207     p_buffer_start =    p_vout->yuv.p_buffer;
1208     p_offset_start =    p_vout->yuv.p_offset;
1209     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1210                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1211
1212     /*
1213      * Perform conversion
1214      */
1215     i_scale_count = i_pic_height;
1216     for( i_y = 0; i_y < i_height; i_y++ )
1217     {
1218         /* Mark beginnning of line for possible later line copy, and initialize
1219          * buffer */
1220         p_pic_start =   p_pic;
1221         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1222
1223         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1224          * pixels wide blocks */
1225         for( i_x = i_width / 16; i_x--;  )
1226         {
1227             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
1228             CONVERT_YUV_PIXEL(1);  CONVERT_YUV_PIXEL(1);
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         }
1236
1237         /* Do horizontal and vertical scaling */
1238         SCALE_WIDTH;
1239         SCALE_HEIGHT(444, 1);
1240     }
1241 }
1242
1243 /*****************************************************************************
1244  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1245  *****************************************************************************/
1246 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,
1247                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1248                                 int i_matrix_coefficients )
1249 {
1250 /* MMX version */
1251   //  int                 i_chroma_width, i_chroma_skip;      /* width and eol for chroma */
1252 /*
1253     i_chroma_width =    i_width / 2;
1254     i_chroma_skip =     i_skip / 2;
1255     ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1256                            (i_width + i_skip) * sizeof( yuv_data_t ),
1257                            (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1258                            i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1259                            p_vout->i_screen_depth == 15 );
1260 */
1261     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1262     int         i_vertical_scaling;                 /* vertical scaling type */
1263     int         i_x, i_y;                 /* horizontal and vertical indexes */
1264     int         i_scale_count;                       /* scale modulo counter */
1265     int         i_uval, i_vval;                           /* U and V samples */
1266     int         i_red, i_green, i_blue;          /* U and V modified samples */
1267     int         i_chroma_width;                              /* chroma width */
1268     u16 *       p_yuv;                              /* base conversion table */
1269     u16 *       p_ybase;                     /* Y dependant conversion table */
1270     u16 *       p_pic_start;       /* beginning of the current line for copy */
1271     u16 *       p_buffer_start;                   /* conversion buffer start */
1272     u16 *       p_buffer;                       /* conversion buffer pointer */
1273     int *       p_offset_start;                        /* offset array start */
1274     int *       p_offset;                            /* offset array pointer */
1275
1276     /*
1277      * Initialize some values  - i_pic_line_width will store the line skip
1278      */
1279     i_pic_line_width -= i_pic_width;
1280     i_chroma_width =    i_width / 2;
1281     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1282     p_buffer_start =    p_vout->yuv.p_buffer;
1283     p_offset_start =    p_vout->yuv.p_offset;
1284     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1285                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1286
1287     /*
1288      * Perform conversion
1289      */
1290     i_scale_count = i_pic_height;
1291     for( i_y = 0; i_y < i_height; i_y++ )
1292     {
1293         /* Mark beginnning of line for possible later line copy, and initialize
1294          * buffer */
1295         p_pic_start =   p_pic;
1296         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1297
1298         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1299          * pixels wide blocks */
1300         for( i_x = i_width / 16; i_x--;  )
1301         {
1302             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1303             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1304             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
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         }
1311
1312         /* Do horizontal and vertical scaling */
1313         SCALE_WIDTH;
1314         SCALE_HEIGHT(420, 2);
1315     }
1316 }
1317
1318 /*****************************************************************************
1319  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1320  *****************************************************************************/
1321 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,
1322                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1323                                 int i_matrix_coefficients )
1324 {
1325     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1326     int         i_vertical_scaling;                 /* vertical scaling type */
1327     int         i_x, i_y;                 /* horizontal and vertical indexes */
1328     int         i_scale_count;                       /* scale modulo counter */
1329     int         i_uval, i_vval;                           /* U and V samples */
1330     int         i_red, i_green, i_blue;          /* U and V modified samples */
1331     int         i_chroma_width;                              /* chroma width */
1332     u16 *       p_yuv;                              /* base conversion table */
1333     u16 *       p_ybase;                     /* Y dependant conversion table */
1334     u16 *       p_pic_start;       /* beginning of the current line for copy */
1335     u16 *       p_buffer_start;                   /* conversion buffer start */
1336     u16 *       p_buffer;                       /* conversion buffer pointer */
1337     int *       p_offset_start;                        /* offset array start */
1338     int *       p_offset;                            /* offset array pointer */
1339
1340     /*
1341      * Initialize some values  - i_pic_line_width will store the line skip
1342      */
1343     i_pic_line_width -= i_pic_width;
1344     i_chroma_width =    i_width / 2;
1345     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1346     p_buffer_start =    p_vout->yuv.p_buffer;
1347     p_offset_start =    p_vout->yuv.p_offset;
1348     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1349                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1350
1351     /*
1352      * Perform conversion
1353      */
1354     i_scale_count = i_pic_height;
1355     for( i_y = 0; i_y < i_height; i_y++ )
1356     {
1357         /* Mark beginnning of line for possible later line copy, and initialize
1358          * buffer */
1359         p_pic_start =   p_pic;
1360         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1361
1362         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1363          * pixels wide blocks */
1364         for( i_x = i_width / 16; i_x--;  )
1365         {
1366             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1367             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
1368             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
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         }
1375
1376         /* Do horizontal and vertical scaling */
1377         SCALE_WIDTH;
1378         SCALE_HEIGHT(422, 2);
1379     }
1380 }
1381
1382 /*****************************************************************************
1383  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1384  *****************************************************************************/
1385 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,
1386                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1387                                 int i_matrix_coefficients )
1388 {
1389     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1390     int         i_vertical_scaling;                 /* vertical scaling type */
1391     int         i_x, i_y;                 /* horizontal and vertical indexes */
1392     int         i_scale_count;                       /* scale modulo counter */
1393     int         i_uval, i_vval;                           /* U and V samples */
1394     int         i_red, i_green, i_blue;          /* U and V modified samples */
1395     int         i_chroma_width;                    /* chroma width, not used */
1396     u16 *       p_yuv;                              /* base conversion table */
1397     u16 *       p_ybase;                     /* Y dependant conversion table */
1398     u16 *       p_pic_start;       /* beginning of the current line for copy */
1399     u16 *       p_buffer_start;                   /* conversion buffer start */
1400     u16 *       p_buffer;                       /* conversion buffer pointer */
1401     int *       p_offset_start;                        /* offset array start */
1402     int *       p_offset;                            /* offset array pointer */
1403
1404     /*
1405      * Initialize some values  - i_pic_line_width will store the line skip
1406      */
1407     i_pic_line_width -= i_pic_width;
1408     p_yuv =             p_vout->yuv.yuv.p_rgb16;
1409     p_buffer_start =    p_vout->yuv.p_buffer;
1410     p_offset_start =    p_vout->yuv.p_offset;
1411     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1412                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1413
1414     /*
1415      * Perform conversion
1416      */
1417     i_scale_count = i_pic_height;
1418     for( i_y = 0; i_y < i_height; i_y++ )
1419     {
1420         /* Mark beginnning of line for possible later line copy, and initialize
1421          * buffer */
1422         p_pic_start =   p_pic;
1423         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1424
1425         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1426          * pixels wide blocks */
1427         for( i_x = i_width / 16; i_x--;  )
1428         {
1429             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1430             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
1431             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
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         }
1438
1439         /* Do horizontal and vertical scaling */
1440         SCALE_WIDTH;
1441         SCALE_HEIGHT(444, 2);
1442     }
1443 }
1444
1445 /*****************************************************************************
1446  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1447  *****************************************************************************/
1448 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,
1449                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1450                                 int i_matrix_coefficients )
1451 {
1452     //???
1453 }
1454
1455 /*****************************************************************************
1456  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1457  *****************************************************************************/
1458 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,
1459                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1460                                 int i_matrix_coefficients )
1461 {
1462     //???
1463 }
1464
1465 /*****************************************************************************
1466  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1467  *****************************************************************************/
1468 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,
1469                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1470                                 int i_matrix_coefficients )
1471 {
1472     //???
1473 }
1474
1475 /*****************************************************************************
1476  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1477  *****************************************************************************/
1478 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,
1479                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1480                                 int i_matrix_coefficients )
1481 {
1482     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1483     int         i_vertical_scaling;                 /* vertical scaling type */
1484     int         i_x, i_y;                 /* horizontal and vertical indexes */
1485     int         i_scale_count;                       /* scale modulo counter */
1486     int         i_uval, i_vval;                           /* U and V samples */
1487     int         i_red, i_green, i_blue;          /* U and V modified samples */
1488     int         i_chroma_width;                              /* chroma width */
1489     u32 *       p_yuv;                              /* base conversion table */
1490     u32 *       p_ybase;                     /* Y dependant conversion table */
1491     u32 *       p_pic_start;       /* beginning of the current line for copy */
1492     u32 *       p_buffer_start;                   /* conversion buffer start */
1493     u32 *       p_buffer;                       /* conversion buffer pointer */
1494     int *       p_offset_start;                        /* offset array start */
1495     int *       p_offset;                            /* offset array pointer */
1496
1497     /*
1498      * Initialize some values  - i_pic_line_width will store the line skip
1499      */
1500     i_pic_line_width -= i_pic_width;
1501     i_chroma_width =    i_width / 2;
1502     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1503     p_buffer_start =    p_vout->yuv.p_buffer;
1504     p_offset_start =    p_vout->yuv.p_offset;
1505     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1506                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1507
1508     /*
1509      * Perform conversion
1510      */
1511     i_scale_count = i_pic_height;
1512     for( i_y = 0; i_y < i_height; i_y++ )
1513     {
1514         /* Mark beginnning of line for possible later line copy, and initialize
1515          * buffer */
1516         p_pic_start =   p_pic;
1517         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1518
1519         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1520          * pixels wide blocks */
1521         for( i_x = i_width / 16; i_x--;  )
1522         {
1523             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1524             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1525             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
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         }
1532
1533         /* Do horizontal and vertical scaling */
1534         SCALE_WIDTH;
1535         SCALE_HEIGHT(420, 4);
1536     }
1537 }
1538
1539 /*****************************************************************************
1540  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1541  *****************************************************************************/
1542 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,
1543                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1544                                 int i_matrix_coefficients )
1545 {
1546     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1547     int         i_vertical_scaling;                 /* vertical scaling type */
1548     int         i_x, i_y;                 /* horizontal and vertical indexes */
1549     int         i_scale_count;                       /* scale modulo counter */
1550     int         i_uval, i_vval;                           /* U and V samples */
1551     int         i_red, i_green, i_blue;          /* U and V modified samples */
1552     int         i_chroma_width;                              /* chroma width */
1553     u32 *       p_yuv;                              /* base conversion table */
1554     u32 *       p_ybase;                     /* Y dependant conversion table */
1555     u32 *       p_pic_start;       /* beginning of the current line for copy */
1556     u32 *       p_buffer_start;                   /* conversion buffer start */
1557     u32 *       p_buffer;                       /* conversion buffer pointer */
1558     int *       p_offset_start;                        /* offset array start */
1559     int *       p_offset;                            /* offset array pointer */
1560
1561     /*
1562      * Initialize some values  - i_pic_line_width will store the line skip
1563      */
1564     i_pic_line_width -= i_pic_width;
1565     i_chroma_width =    i_width / 2;
1566     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1567     p_buffer_start =    p_vout->yuv.p_buffer;
1568     p_offset_start =    p_vout->yuv.p_offset;
1569     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1570                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1571
1572     /*
1573      * Perform conversion
1574      */
1575     i_scale_count = i_pic_height;
1576     for( i_y = 0; i_y < i_height; i_y++ )
1577     {
1578         /* Mark beginnning of line for possible later line copy, and initialize
1579          * buffer */
1580         p_pic_start =   p_pic;
1581         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1582
1583         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1584          * pixels wide blocks */
1585         for( i_x = i_width / 16; i_x--;  )
1586         {
1587             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1588             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
1589             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
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         }
1596
1597         /* Do horizontal and vertical scaling */
1598         SCALE_WIDTH;
1599         SCALE_HEIGHT(422, 4);
1600     }
1601 }
1602
1603 /*****************************************************************************
1604  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1605  *****************************************************************************/
1606 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,
1607                                 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1608                                 int i_matrix_coefficients )
1609 {
1610     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
1611     int         i_vertical_scaling;                 /* vertical scaling type */
1612     int         i_x, i_y;                 /* horizontal and vertical indexes */
1613     int         i_scale_count;                       /* scale modulo counter */
1614     int         i_uval, i_vval;                           /* U and V samples */
1615     int         i_red, i_green, i_blue;          /* U and V modified samples */
1616     int         i_chroma_width;                    /* chroma width, not used */
1617     u32 *       p_yuv;                              /* base conversion table */
1618     u32 *       p_ybase;                     /* Y dependant conversion table */
1619     u32 *       p_pic_start;       /* beginning of the current line for copy */
1620     u32 *       p_buffer_start;                   /* conversion buffer start */
1621     u32 *       p_buffer;                       /* conversion buffer pointer */
1622     int *       p_offset_start;                        /* offset array start */
1623     int *       p_offset;                            /* offset array pointer */
1624
1625     /*
1626      * Initialize some values  - i_pic_line_width will store the line skip
1627      */
1628     i_pic_line_width -= i_pic_width;
1629     p_yuv =             p_vout->yuv.yuv.p_rgb32;
1630     p_buffer_start =    p_vout->yuv.p_buffer;
1631     p_offset_start =    p_vout->yuv.p_offset;
1632     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1633                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1634
1635     /*
1636      * Perform conversion
1637      */
1638     i_scale_count = i_pic_height;
1639     for( i_y = 0; i_y < i_height; i_y++ )
1640     {
1641         /* Mark beginnning of line for possible later line copy, and initialize
1642          * buffer */
1643         p_pic_start =   p_pic;
1644         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
1645
1646         /* Do YUV conversion to buffer - YUV picture is always formed of 16
1647          * pixels wide blocks */
1648         for( i_x = i_width / 16; i_x--;  )
1649         {
1650             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1651             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
1652             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
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         }
1659
1660         /* Do horizontal and vertical scaling */
1661         SCALE_WIDTH;
1662         SCALE_HEIGHT(444, 4);
1663     }
1664 }
1665
1666 //-------------------- walken code follows ------------------------------------
1667
1668 /*
1669  * YUV to RGB routines.
1670  *
1671  * these routines calculate r, g and b values from each pixel's y, u and v.
1672  * these r, g an b values are then passed thru a table lookup to take the
1673  * gamma curve into account and find the corresponding pixel value.
1674  *
1675  * the table must store more than 3*256 values because of the possibility
1676  * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1677  * values are in the following intervals :
1678  * -176 to 255+176 for red
1679  * -133 to 255+133 for green
1680  * -222 to 255+222 for blue
1681  *
1682  * If the input y,u,v values are right, the r,g,b results are not expected
1683  * to move out of the 0 to 255 interval but who knows what will happen in
1684  * real use...
1685  *
1686  * the red, green and blue conversion tables are stored in a single 1935-entry
1687  * array. The respective positions of each component in the array have been
1688  * calculated to minimize the cache interactions of the 3 tables.
1689  */
1690
1691 #if 0
1692 //??
1693 static void yuvToRgb24 (unsigned char * Y,
1694                         unsigned char * U, unsigned char * V,
1695                         char * dest, int table[1935], int width)
1696 {
1697     int i;
1698     int u;
1699     int v;
1700     int uvRed;
1701     int uvGreen;
1702     int uvBlue;
1703     int * tableY;
1704     int tmp24;
1705
1706     i = width >> 3;
1707     while (i--) {
1708         u = *(U++);
1709         v = *(V++);
1710         uvRed = (V_RED_COEF*v) >> SHIFT;
1711         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1712         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1713
1714         tableY = table + *(Y++);
1715         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1716                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1717                         uvGreen] |
1718                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1719         *(dest++) = tmp24;
1720         *(dest++) = tmp24 >> 8;
1721         *(dest++) = tmp24 >> 16;
1722
1723         tableY = table + *(Y++);
1724         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1725                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1726                         uvGreen] |
1727                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1728         *(dest++) = tmp24;
1729         *(dest++) = tmp24 >> 8;
1730         *(dest++) = tmp24 >> 16;
1731
1732         u = *(U++);
1733         v = *(V++);
1734         uvRed = (V_RED_COEF*v) >> SHIFT;
1735         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1736         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1737
1738         tableY = table + *(Y++);
1739         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1740                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1741                         uvGreen] |
1742                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1743         *(dest++) = tmp24;
1744         *(dest++) = tmp24 >> 8;
1745         *(dest++) = tmp24 >> 16;
1746
1747         tableY = table + *(Y++);
1748         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1749                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1750                         uvGreen] |
1751                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1752         *(dest++) = tmp24;
1753         *(dest++) = tmp24 >> 8;
1754         *(dest++) = tmp24 >> 16;
1755
1756         u = *(U++);
1757         v = *(V++);
1758         uvRed = (V_RED_COEF*v) >> SHIFT;
1759         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1760         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1761
1762         tableY = table + *(Y++);
1763         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1764                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1765                         uvGreen] |
1766                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1767         *(dest++) = tmp24;
1768         *(dest++) = tmp24 >> 8;
1769         *(dest++) = tmp24 >> 16;
1770
1771         tableY = table + *(Y++);
1772         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1773                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1774                         uvGreen] |
1775                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1776         *(dest++) = tmp24;
1777         *(dest++) = tmp24 >> 8;
1778         *(dest++) = tmp24 >> 16;
1779
1780         u = *(U++);
1781         v = *(V++);
1782         uvRed = (V_RED_COEF*v) >> SHIFT;
1783         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1784         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1785
1786         tableY = table + *(Y++);
1787         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1788                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1789                         uvGreen] |
1790                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1791         *(dest++) = tmp24;
1792         *(dest++) = tmp24 >> 8;
1793         *(dest++) = tmp24 >> 16;
1794
1795         tableY = table + *(Y++);
1796         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1797                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1798                         uvGreen] |
1799                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1800         *(dest++) = tmp24;
1801         *(dest++) = tmp24 >> 8;
1802         *(dest++) = tmp24 >> 16;
1803     }
1804
1805     i = (width & 7) >> 1;
1806     while (i--) {
1807         u = *(U++);
1808         v = *(V++);
1809         uvRed = (V_RED_COEF*v) >> SHIFT;
1810         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1811         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1812
1813         tableY = table + *(Y++);
1814         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1815                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1816                         uvGreen] |
1817                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1818         *(dest++) = tmp24;
1819         *(dest++) = tmp24 >> 8;
1820         *(dest++) = tmp24 >> 16;
1821
1822         tableY = table + *(Y++);
1823         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1824                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1825                         uvGreen] |
1826                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1827         *(dest++) = tmp24;
1828         *(dest++) = tmp24 >> 8;
1829         *(dest++) = tmp24 >> 16;
1830     }
1831
1832     if (width & 1) {
1833         u = *(U++);
1834         v = *(V++);
1835         uvRed = (V_RED_COEF*v) >> SHIFT;
1836         uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1837         uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1838
1839         tableY = table + *(Y++);
1840         tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1841                  tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1842                         uvGreen] |
1843                  tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1844         *(dest++) = tmp24;
1845         *(dest++) = tmp24 >> 8;
1846         *(dest++) = tmp24 >> 16;
1847     }
1848 }
1849 #endif