]> git.sesse.net Git - vlc/blob - plugins/yuv/transforms_yuv.c
e9c0bf9cbb7b9f77727f9e2683767ce8178fcb1b
[vlc] / plugins / yuv / transforms_yuv.c
1 /*****************************************************************************
2  * transforms_yuv.c: C YUV transformation functions
3  * Provides functions to perform the YUV conversion. The functions provided
4  * here are a complete and portable C implementation, and may be replaced in
5  * certain cases by optimized functions.
6  *****************************************************************************
7  * Copyright (C) 1999, 2000, 2001 VideoLAN
8  *
9  * Authors: Vincent Seguin <ptyx@via.ecp.fr>
10  *          Samuel Hocevar <sam@zoy.org>
11  *          Richard Shepherd <richard@rshepherd.demon.co.uk>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public
24  * License along with this program; if not, write to the
25  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26  * Boston, MA 02111-1307, USA.
27  *****************************************************************************/
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32 #include "defs.h"
33
34 #include <math.h>                                            /* exp(), pow() */
35 #include <errno.h>                                                 /* ENOMEM */
36 #include <stdlib.h>                                                /* free() */
37 #include <string.h>                                            /* strerror() */
38
39 #include "config.h"
40 #include "common.h"
41 #include "threads.h"
42 #include "mtime.h"
43
44 #include "video.h"
45 #include "video_output.h"
46
47 #include "video_common.h"
48 #include "transforms_common.h"
49 #include "transforms_yuv.h"
50
51 #include "intf_msg.h"
52
53 /*****************************************************************************
54  * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
55  *****************************************************************************/
56 void ConvertY4Gray8( YUV_ARGS_8BPP )
57 {
58     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
59     int         i_vertical_scaling;                 /* vertical scaling type */
60     int         i_x, i_y;                 /* horizontal and vertical indexes */
61     int         i_scale_count;                       /* scale modulo counter */
62     int         i_chroma_width;                    /* chroma width, not used */
63     u8 *        p_gray;                             /* base conversion table */
64     u8 *        p_pic_start;       /* beginning of the current line for copy */
65     u8 *        p_buffer_start;                   /* conversion buffer start */
66     u8 *        p_buffer;                       /* conversion buffer pointer */
67     int *       p_offset_start;                        /* offset array start */
68     int *       p_offset;                            /* offset array pointer */
69
70     /*
71      * Initialize some values  - i_pic_line_width will store the line skip
72      */
73     i_pic_line_width -= i_pic_width;
74     p_gray =            p_vout->yuv.yuv.p_gray8;
75     p_buffer_start =    p_vout->yuv.p_buffer;
76     p_offset_start =    p_vout->yuv.p_offset;
77     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
78                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
79
80     /*
81      * Perform conversion
82      */
83     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
84     for( i_y = 0; i_y < i_height; i_y++ )
85     {
86         /* Mark beginnning of line for possible later line copy, and initialize
87          * buffer */
88         p_pic_start =   p_pic;
89         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
90
91         /* Do YUV conversion to buffer - YUV picture is always formed of 16
92          * pixels wide blocks */
93         for( i_x = i_width / 16; i_x--;  )
94         {
95             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
96             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
97             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
98             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
99             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
100             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
101             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
102             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
103         }
104
105         /* Do horizontal and vertical scaling */
106         SCALE_WIDTH;
107         SCALE_HEIGHT(400, 1);
108     }
109 }
110
111 /*****************************************************************************
112  * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
113  *****************************************************************************/
114 void ConvertYUV420RGB8( YUV_ARGS_8BPP )
115 {
116     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
117     int         i_vertical_scaling;                 /* vertical scaling type */
118     int         i_x, i_y;                 /* horizontal and vertical indexes */
119     int         i_scale_count;                       /* scale modulo counter */
120     int         i_real_y;                                           /* y % 4 */
121     u8 *        p_lookup;                                    /* lookup table */
122     int         i_chroma_width;                              /* chroma width */
123     int *       p_offset_start;                        /* offset array start */
124     int *       p_offset;                            /* offset array pointer */
125
126     /* 
127      * The dithering matrices
128      */
129     static int dither10[4] = {  0x0,  0x8,  0x2,  0xa };
130     static int dither11[4] = {  0xc,  0x4,  0xe,  0x6 };
131     static int dither12[4] = {  0x3,  0xb,  0x1,  0x9 };
132     static int dither13[4] = {  0xf,  0x7,  0xd,  0x5 };
133
134     static int dither20[4] = {  0x0, 0x10,  0x4, 0x14 };
135     static int dither21[4] = { 0x18,  0x8, 0x1c,  0xc };
136     static int dither22[4] = {  0x6, 0x16,  0x2, 0x12 };
137     static int dither23[4] = { 0x1e,  0xe, 0x1a,  0xa };
138
139    /*
140      * Initialize some values  - i_pic_line_width will store the line skip
141      */
142     i_pic_line_width -= i_pic_width;
143     i_chroma_width =    i_width / 2;
144     p_offset_start =    p_vout->yuv.p_offset;
145     p_lookup =          p_vout->yuv.p_base;
146     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
147                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 1 );
148
149     /*
150      * Perform conversion
151      */
152     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
153     i_real_y = 0;
154     for( i_y = 0; i_y < i_height; i_y++ )
155     {
156         /* Do horizontal and vertical scaling */
157         SCALE_WIDTH_DITHER( 420 );
158         SCALE_HEIGHT_DITHER( 420 );
159     }
160 }
161
162 /*****************************************************************************
163  * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
164  *****************************************************************************/
165 void ConvertYUV422RGB8( YUV_ARGS_8BPP )
166 {
167     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, bpp = 8" );
168 }
169
170 /*****************************************************************************
171  * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
172  *****************************************************************************/
173 void ConvertYUV444RGB8( YUV_ARGS_8BPP )
174 {
175     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, bpp = 8" );
176 }
177
178 /*****************************************************************************
179  * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
180  *****************************************************************************/
181 void ConvertY4Gray16( YUV_ARGS_16BPP )
182 {
183     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
184     int         i_vertical_scaling;                 /* vertical scaling type */
185     int         i_x, i_y;                 /* horizontal and vertical indexes */
186     int         i_scale_count;                       /* scale modulo counter */
187     int         i_chroma_width;                    /* chroma width, not used */
188     u16 *       p_gray;                             /* base conversion table */
189     u16 *       p_pic_start;       /* beginning of the current line for copy */
190     u16 *       p_buffer_start;                   /* conversion buffer start */
191     u16 *       p_buffer;                       /* conversion buffer pointer */
192     int *       p_offset_start;                        /* offset array start */
193     int *       p_offset;                            /* offset array pointer */
194
195     /*
196      * Initialize some values  - i_pic_line_width will store the line skip
197      */
198     i_pic_line_width -= i_pic_width;
199     p_gray =            p_vout->yuv.yuv.p_gray16;
200     p_buffer_start =    p_vout->yuv.p_buffer;
201     p_offset_start =    p_vout->yuv.p_offset;
202     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
203                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
204
205     /*
206      * Perform conversion
207      */
208     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
209     for( i_y = 0; i_y < i_height; i_y++ )
210     {
211         /* Mark beginnning of line for possible later line copy, and initialize
212          * buffer */
213         p_pic_start =   p_pic;
214         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
215
216         /* Do YUV conversion to buffer - YUV picture is always formed of 16
217          * pixels wide blocks */
218         for( i_x = i_width / 16; i_x--;  )
219         {
220             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
221             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
222             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
223             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
224             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
225             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
226             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
227             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
228         }
229
230         /* Do horizontal and vertical scaling */
231         SCALE_WIDTH;
232         SCALE_HEIGHT(400, 2);
233     }
234 }
235
236 /*****************************************************************************
237  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
238  *****************************************************************************/
239 void ConvertYUV420RGB16( YUV_ARGS_16BPP )
240 {
241     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
242     int         i_vertical_scaling;                 /* vertical scaling type */
243     int         i_x, i_y;                 /* horizontal and vertical indexes */
244     int         i_scale_count;                       /* scale modulo counter */
245     int         i_uval, i_vval;                           /* U and V samples */
246     int         i_red, i_green, i_blue;          /* U and V modified samples */
247     int         i_chroma_width;                              /* chroma width */
248     u16 *       p_yuv;                              /* base conversion table */
249     u16 *       p_ybase;                     /* Y dependant conversion table */
250     u16 *       p_pic_start;       /* beginning of the current line for copy */
251     u16 *       p_buffer_start;                   /* conversion buffer start */
252     u16 *       p_buffer;                       /* conversion buffer pointer */
253     int *       p_offset_start;                        /* offset array start */
254     int *       p_offset;                            /* offset array pointer */
255
256     /*
257      * Initialize some values  - i_pic_line_width will store the line skip
258      */
259     i_pic_line_width -= i_pic_width;
260     i_chroma_width =    i_width / 2;
261     p_yuv =             p_vout->yuv.yuv.p_rgb16;
262     p_buffer_start =    p_vout->yuv.p_buffer;
263     p_offset_start =    p_vout->yuv.p_offset;
264     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
265                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
266
267     /*
268      * Perform conversion
269      */
270     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
271     for( i_y = 0; i_y < i_height; i_y++ )
272     {
273         /* Mark beginnning of line for possible later line copy, and initialize
274          * buffer */
275         p_pic_start =   p_pic;
276         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
277
278         /* Do YUV conversion to buffer - YUV picture is always formed of 16
279          * pixels wide blocks */
280         for( i_x = i_width / 16; i_x--;  )
281         {
282             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
283             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
284             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
285             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
286             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
287             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
288             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
289             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
290         }
291
292         /* Do horizontal and vertical scaling */
293         SCALE_WIDTH;
294         SCALE_HEIGHT(420, 2);
295     }
296 }
297
298 /*****************************************************************************
299  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
300  *****************************************************************************/
301 void ConvertYUV422RGB16( YUV_ARGS_16BPP )
302 {
303     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
304     int         i_vertical_scaling;                 /* vertical scaling type */
305     int         i_x, i_y;                 /* horizontal and vertical indexes */
306     int         i_scale_count;                       /* scale modulo counter */
307     int         i_uval, i_vval;                           /* U and V samples */
308     int         i_red, i_green, i_blue;          /* U and V modified samples */
309     int         i_chroma_width;                              /* chroma width */
310     u16 *       p_yuv;                              /* base conversion table */
311     u16 *       p_ybase;                     /* Y dependant conversion table */
312     u16 *       p_pic_start;       /* beginning of the current line for copy */
313     u16 *       p_buffer_start;                   /* conversion buffer start */
314     u16 *       p_buffer;                       /* conversion buffer pointer */
315     int *       p_offset_start;                        /* offset array start */
316     int *       p_offset;                            /* offset array pointer */
317
318     /*
319      * Initialize some values  - i_pic_line_width will store the line skip
320      */
321     i_pic_line_width -= i_pic_width;
322     i_chroma_width =    i_width / 2;
323     p_yuv =             p_vout->yuv.yuv.p_rgb16;
324     p_buffer_start =    p_vout->yuv.p_buffer;
325     p_offset_start =    p_vout->yuv.p_offset;
326     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
327                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
328
329     /*
330      * Perform conversion
331      */
332     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
333     for( i_y = 0; i_y < i_height; i_y++ )
334     {
335         /* Mark beginnning of line for possible later line copy, and initialize
336          * buffer */
337         p_pic_start =   p_pic;
338         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
339
340         /* Do YUV conversion to buffer - YUV picture is always formed of 16
341          * pixels wide blocks */
342         for( i_x = i_width / 16; i_x--;  )
343         {
344             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
345             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
346             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
347             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
348             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
349             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
350             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
351             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
352         }
353
354         /* Do horizontal and vertical scaling */
355         SCALE_WIDTH;
356         SCALE_HEIGHT(422, 2);
357     }
358 }
359
360 /*****************************************************************************
361  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
362  *****************************************************************************/
363 void ConvertYUV444RGB16( YUV_ARGS_16BPP )
364 {
365     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
366     int         i_vertical_scaling;                 /* vertical scaling type */
367     int         i_x, i_y;                 /* horizontal and vertical indexes */
368     int         i_scale_count;                       /* scale modulo counter */
369     int         i_uval, i_vval;                           /* U and V samples */
370     int         i_red, i_green, i_blue;          /* U and V modified samples */
371     int         i_chroma_width;                    /* chroma width, not used */
372     u16 *       p_yuv;                              /* base conversion table */
373     u16 *       p_ybase;                     /* Y dependant conversion table */
374     u16 *       p_pic_start;       /* beginning of the current line for copy */
375     u16 *       p_buffer_start;                   /* conversion buffer start */
376     u16 *       p_buffer;                       /* conversion buffer pointer */
377     int *       p_offset_start;                        /* offset array start */
378     int *       p_offset;                            /* offset array pointer */
379
380     /*
381      * Initialize some values  - i_pic_line_width will store the line skip
382      */
383     i_pic_line_width -= i_pic_width;
384     p_yuv =             p_vout->yuv.yuv.p_rgb16;
385     p_buffer_start =    p_vout->yuv.p_buffer;
386     p_offset_start =    p_vout->yuv.p_offset;
387     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
388                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
389
390     /*
391      * Perform conversion
392      */
393     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
394     for( i_y = 0; i_y < i_height; i_y++ )
395     {
396         /* Mark beginnning of line for possible later line copy, and initialize
397          * buffer */
398         p_pic_start =   p_pic;
399         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
400
401         /* Do YUV conversion to buffer - YUV picture is always formed of 16
402          * pixels wide blocks */
403         for( i_x = i_width / 16; i_x--;  )
404         {
405             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
406             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
407             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
408             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
409             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
410             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
411             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
412             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
413         }
414
415         /* Do horizontal and vertical scaling */
416         SCALE_WIDTH;
417         SCALE_HEIGHT(444, 2);
418     }
419 }
420
421 /*****************************************************************************
422  * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 2 Bpp
423  *****************************************************************************/
424 void ConvertY4Gray24( YUV_ARGS_24BPP )
425 {
426     intf_ErrMsg( "yuv error: unhandled function, grayscale, bpp = 24" );
427 }
428
429 /*****************************************************************************
430  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 2 Bpp
431  *****************************************************************************/
432 void ConvertYUV420RGB24( YUV_ARGS_24BPP )
433 {
434     intf_ErrMsg( "yuv error: unhandled function, chroma = 420, bpp = 24" );
435 }
436
437 /*****************************************************************************
438  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 2 Bpp
439  *****************************************************************************/
440 void ConvertYUV422RGB24( YUV_ARGS_24BPP )
441 {
442     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, bpp = 24" );
443 }
444
445 /*****************************************************************************
446  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 2 Bpp
447  *****************************************************************************/
448 void ConvertYUV444RGB24( YUV_ARGS_24BPP )
449 {
450     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, bpp = 24" );
451 }
452
453 /*****************************************************************************
454  * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
455  *****************************************************************************/
456 void ConvertY4Gray32( YUV_ARGS_32BPP )
457 {
458     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
459     int         i_vertical_scaling;                 /* vertical scaling type */
460     int         i_x, i_y;                 /* horizontal and vertical indexes */
461     int         i_scale_count;                       /* scale modulo counter */
462     int         i_chroma_width;                    /* chroma width, not used */
463     u32 *       p_gray;                             /* base conversion table */
464     u32 *       p_pic_start;       /* beginning of the current line for copy */
465     u32 *       p_buffer_start;                   /* conversion buffer start */
466     u32 *       p_buffer;                       /* conversion buffer pointer */
467     int *       p_offset_start;                        /* offset array start */
468     int *       p_offset;                            /* offset array pointer */
469
470     /*
471      * Initialize some values  - i_pic_line_width will store the line skip
472      */
473     i_pic_line_width -= i_pic_width;
474     p_gray =            p_vout->yuv.yuv.p_gray32;
475     p_buffer_start =    p_vout->yuv.p_buffer;
476     p_offset_start =    p_vout->yuv.p_offset;
477     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
478                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
479
480     /*
481      * Perform conversion
482      */
483     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
484     for( i_y = 0; i_y < i_height; i_y++ )
485     {
486         /* Mark beginnning of line for possible later line copy, and initialize
487          * buffer */
488         p_pic_start =   p_pic;
489         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
490
491         /* Do YUV conversion to buffer - YUV picture is always formed of 16
492          * pixels wide blocks */
493         for( i_x = i_width / 16; i_x--;  )
494         {
495             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
496             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
497             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
498             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
499             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
500             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
501             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
502             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
503         }
504
505         /* Do horizontal and vertical scaling */
506         SCALE_WIDTH;
507         SCALE_HEIGHT(400, 4);
508     }
509 }
510
511 /*****************************************************************************
512  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
513  *****************************************************************************/
514 void ConvertYUV420RGB32( YUV_ARGS_32BPP )
515 {
516     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
517     int         i_vertical_scaling;                 /* vertical scaling type */
518     int         i_x, i_y;                 /* horizontal and vertical indexes */
519     int         i_scale_count;                       /* scale modulo counter */
520     int         i_uval, i_vval;                           /* U and V samples */
521     int         i_red, i_green, i_blue;          /* U and V modified samples */
522     int         i_chroma_width;                              /* chroma width */
523     u32 *       p_yuv;                              /* base conversion table */
524     u32 *       p_ybase;                     /* Y dependant conversion table */
525     u32 *       p_pic_start;       /* beginning of the current line for copy */
526     u32 *       p_buffer_start;                   /* conversion buffer start */
527     u32 *       p_buffer;                       /* conversion buffer pointer */
528     int *       p_offset_start;                        /* offset array start */
529     int *       p_offset;                            /* offset array pointer */
530
531     /*
532      * Initialize some values  - i_pic_line_width will store the line skip
533      */
534     i_pic_line_width -= i_pic_width;
535     i_chroma_width =    i_width / 2;
536     p_yuv =             p_vout->yuv.yuv.p_rgb32;
537     p_buffer_start =    p_vout->yuv.p_buffer;
538     p_offset_start =    p_vout->yuv.p_offset;
539     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
540                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
541
542     /*
543      * Perform conversion
544      */
545     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
546     for( i_y = 0; i_y < i_height; i_y++ )
547     {
548         /* Mark beginnning of line for possible later line copy, and initialize
549          * buffer */
550         p_pic_start =   p_pic;
551         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
552
553         /* Do YUV conversion to buffer - YUV picture is always formed of 16
554          * pixels wide blocks */
555         for( i_x = i_width / 16; i_x--;  )
556         {
557             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
558             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
559             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
560             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
561             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
562             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
563             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
564             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
565         }
566
567         /* Do horizontal and vertical scaling */
568         SCALE_WIDTH;
569         SCALE_HEIGHT(420, 4);
570     }
571 }
572
573 /*****************************************************************************
574  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
575  *****************************************************************************/
576 void ConvertYUV422RGB32( YUV_ARGS_32BPP )
577 {
578     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
579     int         i_vertical_scaling;                 /* vertical scaling type */
580     int         i_x, i_y;                 /* horizontal and vertical indexes */
581     int         i_scale_count;                       /* scale modulo counter */
582     int         i_uval, i_vval;                           /* U and V samples */
583     int         i_red, i_green, i_blue;          /* U and V modified samples */
584     int         i_chroma_width;                              /* chroma width */
585     u32 *       p_yuv;                              /* base conversion table */
586     u32 *       p_ybase;                     /* Y dependant conversion table */
587     u32 *       p_pic_start;       /* beginning of the current line for copy */
588     u32 *       p_buffer_start;                   /* conversion buffer start */
589     u32 *       p_buffer;                       /* conversion buffer pointer */
590     int *       p_offset_start;                        /* offset array start */
591     int *       p_offset;                            /* offset array pointer */
592
593     /*
594      * Initialize some values  - i_pic_line_width will store the line skip
595      */
596     i_pic_line_width -= i_pic_width;
597     i_chroma_width =    i_width / 2;
598     p_yuv =             p_vout->yuv.yuv.p_rgb32;
599     p_buffer_start =    p_vout->yuv.p_buffer;
600     p_offset_start =    p_vout->yuv.p_offset;
601     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
602                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
603
604     /*
605      * Perform conversion
606      */
607     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
608     for( i_y = 0; i_y < i_height; i_y++ )
609     {
610         /* Mark beginnning of line for possible later line copy, and initialize
611          * buffer */
612         p_pic_start =   p_pic;
613         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
614
615         /* Do YUV conversion to buffer - YUV picture is always formed of 16
616          * pixels wide blocks */
617         for( i_x = i_width / 16; i_x--;  )
618         {
619             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
620             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
621             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
622             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
623             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
624             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
625             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
626             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
627         }
628
629         /* Do horizontal and vertical scaling */
630         SCALE_WIDTH;
631         SCALE_HEIGHT(422, 4);
632     }
633 }
634
635 /*****************************************************************************
636  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
637  *****************************************************************************/
638 void ConvertYUV444RGB32( YUV_ARGS_32BPP )
639 {
640     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
641     int         i_vertical_scaling;                 /* vertical scaling type */
642     int         i_x, i_y;                 /* horizontal and vertical indexes */
643     int         i_scale_count;                       /* scale modulo counter */
644     int         i_uval, i_vval;                           /* U and V samples */
645     int         i_red, i_green, i_blue;          /* U and V modified samples */
646     int         i_chroma_width;                    /* chroma width, not used */
647     u32 *       p_yuv;                              /* base conversion table */
648     u32 *       p_ybase;                     /* Y dependant conversion table */
649     u32 *       p_pic_start;       /* beginning of the current line for copy */
650     u32 *       p_buffer_start;                   /* conversion buffer start */
651     u32 *       p_buffer;                       /* conversion buffer pointer */
652     int *       p_offset_start;                        /* offset array start */
653     int *       p_offset;                            /* offset array pointer */
654
655     /*
656      * Initialize some values  - i_pic_line_width will store the line skip
657      */
658     i_pic_line_width -= i_pic_width;
659     p_yuv =             p_vout->yuv.yuv.p_rgb32;
660     p_buffer_start =    p_vout->yuv.p_buffer;
661     p_offset_start =    p_vout->yuv.p_offset;
662     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
663                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
664
665     /*
666      * Perform conversion
667      */
668     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
669     for( i_y = 0; i_y < i_height; i_y++ )
670     {
671         /* Mark beginnning of line for possible later line copy, and initialize
672          * buffer */
673         p_pic_start =   p_pic;
674         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
675
676         /* Do YUV conversion to buffer - YUV picture is always formed of 16
677          * pixels wide blocks */
678         for( i_x = i_width / 16; i_x--;  )
679         {
680             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
681             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
682             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
683             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
684             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
685             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
686             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
687             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
688         }
689
690         /* Do horizontal and vertical scaling */
691         SCALE_WIDTH;
692         SCALE_HEIGHT(444, 4);
693     }
694 }
695
696 static __inline__ void yuv2YCbCr422_inner( u8 *p_y, u8 *p_u, u8 *p_v,
697                                            u8 *p_out, int i_width_by_4 )
698 {
699     int i_x;
700
701     for( i_x = 0 ; i_x < 4 * i_width_by_4 ; ++i_x )
702     {
703         *p_out++ = p_y[ 2 * i_x ];
704         *p_out++ = p_u[ i_x ];
705         *p_out++ = p_y[ 2 * i_x + 1 ];
706         *p_out++ = p_v[ i_x ];
707     }
708 }
709
710 void ConvertYUV420YCbr8    ( YUV_ARGS_8BPP )
711 {
712     intf_ErrMsg( "yuv error: unhandled function, chroma = 420, YCbr = 8" );
713 }
714
715 void ConvertYUV422YCbr8    ( YUV_ARGS_8BPP )
716 {
717     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, YCbr = 8" );
718
719 }
720 void ConvertYUV444YCbr8    ( YUV_ARGS_8BPP )
721 {
722     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, YCbr = 8" );
723
724 }
725
726 /*****************************************************************************
727  * yuv2YCbCr422: color YUV 4:2:0 to color YCbCr 16bpp
728  *****************************************************************************/
729 void ConvertYUV420YCbr16    ( YUV_ARGS_16BPP )
730 {
731     int i_y;
732
733     for( i_y = 0 ; i_y < i_height ; ++i_y )
734     {
735         yuv2YCbCr422_inner( p_y, p_u, p_v, (u8 *)p_pic, i_width / 8 );
736
737         p_pic += i_width * 2;
738         
739         p_y += i_width;
740
741         if( i_y & 0x1 )
742         {
743             p_u += i_width / 2;
744             p_v += i_width / 2;
745         }
746     }
747 }
748
749 void ConvertYUV422YCbr16    ( YUV_ARGS_16BPP )
750 {
751     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, YCbr = 16" );
752
753 }
754 void ConvertYUV444YCbr16    ( YUV_ARGS_16BPP )
755 {
756     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, YCbr = 16" );
757
758 }
759
760 void ConvertYUV420YCbr24    ( YUV_ARGS_24BPP )
761 {
762     intf_ErrMsg( "yuv error: unhandled function, chroma = 420, YCbr = 24" );
763
764 }
765
766 void ConvertYUV422YCbr24    ( YUV_ARGS_24BPP )
767 {
768     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, YCbr = 24" );
769
770 }
771
772 void ConvertYUV444YCbr24    ( YUV_ARGS_24BPP )
773 {
774     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, YCbr = 24" );
775
776 }
777
778 void ConvertYUV420YCbr32    ( YUV_ARGS_32BPP )
779 {
780     intf_ErrMsg( "yuv error: unhandled function, chroma = 420, YCbr = 32" );
781
782 }
783
784 void ConvertYUV422YCbr32    ( YUV_ARGS_32BPP )
785 {
786     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, YCbr = 32" );
787
788 }
789 void ConvertYUV444YCbr32    ( YUV_ARGS_32BPP )
790 {
791     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, YCbr = 32" );
792
793 }
794