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