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