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