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