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