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