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