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