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