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