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