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