]> git.sesse.net Git - vlc/blob - plugins/yuv/transforms_yuv.c
eabdeb4c8a7391d73b7b89d46163e91c0fc28779
[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 #include "plugins.h"
42
43 #include "video.h"
44 #include "video_output.h"
45
46 #include "video_common.h"
47 #include "transforms_common.h"
48 #include "transforms_yuv.h"
49
50 #include "intf_msg.h"
51
52 /*****************************************************************************
53  * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
54  *****************************************************************************/
55 void ConvertY4Gray8( YUV_ARGS_8BPP )
56 {
57     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
58     int         i_vertical_scaling;                 /* vertical scaling type */
59     int         i_x, i_y;                 /* horizontal and vertical indexes */
60     int         i_scale_count;                       /* scale modulo counter */
61     int         i_chroma_width;                    /* chroma width, not used */
62     u8 *        p_gray;                             /* base conversion table */
63     u8 *        p_pic_start;       /* beginning of the current line for copy */
64     u8 *        p_buffer_start;                   /* conversion buffer start */
65     u8 *        p_buffer;                       /* conversion buffer pointer */
66     int *       p_offset_start;                        /* offset array start */
67     int *       p_offset;                            /* offset array pointer */
68
69     /*
70      * Initialize some values  - i_pic_line_width will store the line skip
71      */
72     i_pic_line_width -= i_pic_width;
73     p_gray =            p_vout->yuv.yuv.p_gray8;
74     p_buffer_start =    p_vout->yuv.p_buffer;
75     p_offset_start =    p_vout->yuv.p_offset;
76     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
77                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
78
79     /*
80      * Perform conversion
81      */
82     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
83     for( i_y = 0; i_y < i_height; i_y++ )
84     {
85         /* Mark beginnning of line for possible later line copy, and initialize
86          * buffer */
87         p_pic_start =   p_pic;
88         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
89
90         /* Do YUV conversion to buffer - YUV picture is always formed of 16
91          * pixels wide blocks */
92         for( i_x = i_width / 16; i_x--;  )
93         {
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             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
102         }
103
104         /* Do horizontal and vertical scaling */
105         SCALE_WIDTH;
106         SCALE_HEIGHT(400, 1);
107     }
108 }
109
110 /*****************************************************************************
111  * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
112  *****************************************************************************/
113 void ConvertYUV420RGB8( YUV_ARGS_8BPP )
114 {
115     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
116     int         i_vertical_scaling;                 /* vertical scaling type */
117     int         i_x, i_y;                 /* horizontal and vertical indexes */
118     int         i_scale_count;                       /* scale modulo counter */
119     int         i_real_y;                                           /* y % 4 */
120     u8 *        p_lookup;                                    /* lookup table */
121     int         i_chroma_width;                              /* chroma width */
122     int *       p_offset_start;                        /* offset array start */
123     int *       p_offset;                            /* offset array pointer */
124
125     /* 
126      * The dithering matrices
127      */
128     static int dither10[4] = {  0x0,  0x8,  0x2,  0xa };
129     static int dither11[4] = {  0xc,  0x4,  0xe,  0x6 };
130     static int dither12[4] = {  0x3,  0xb,  0x1,  0x9 };
131     static int dither13[4] = {  0xf,  0x7,  0xd,  0x5 };
132
133     static int dither20[4] = {  0x0, 0x10,  0x4, 0x14 };
134     static int dither21[4] = { 0x18,  0x8, 0x1c,  0xc };
135     static int dither22[4] = {  0x6, 0x16,  0x2, 0x12 };
136     static int dither23[4] = { 0x1e,  0xe, 0x1a,  0xa };
137
138     /*
139      * Initialize some values  - i_pic_line_width will store the line skip
140      */
141     i_pic_line_width -= i_pic_width;
142     i_chroma_width =    i_width / 2;
143     p_offset_start =    p_vout->yuv.p_offset;
144     p_lookup =          p_vout->yuv.p_base;
145     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
146                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 1 );
147
148     /*
149      * Perform conversion
150      */
151     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
152     i_real_y = 0;
153     for( i_y = 0; i_y < i_height; i_y++ )
154     {
155         /* Do horizontal and vertical scaling */
156         SCALE_WIDTH_DITHER( 420 );
157         SCALE_HEIGHT_DITHER( 420 );
158     }
159 }
160
161 /*****************************************************************************
162  * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
163  *****************************************************************************/
164 void ConvertYUV422RGB8( YUV_ARGS_8BPP )
165 {
166     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, bpp = 8" );
167 }
168
169 /*****************************************************************************
170  * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
171  *****************************************************************************/
172 void ConvertYUV444RGB8( YUV_ARGS_8BPP )
173 {
174     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, bpp = 8" );
175 }
176
177 /*****************************************************************************
178  * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
179  *****************************************************************************/
180 void ConvertY4Gray16( YUV_ARGS_16BPP )
181 {
182     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
183     int         i_vertical_scaling;                 /* vertical scaling type */
184     int         i_x, i_y;                 /* horizontal and vertical indexes */
185     int         i_scale_count;                       /* scale modulo counter */
186     int         i_chroma_width;                    /* chroma width, not used */
187     u16 *       p_gray;                             /* base conversion table */
188     u16 *       p_pic_start;       /* beginning of the current line for copy */
189     u16 *       p_buffer_start;                   /* conversion buffer start */
190     u16 *       p_buffer;                       /* conversion buffer pointer */
191     int *       p_offset_start;                        /* offset array start */
192     int *       p_offset;                            /* offset array pointer */
193
194     /*
195      * Initialize some values  - i_pic_line_width will store the line skip
196      */
197     i_pic_line_width -= i_pic_width;
198     p_gray =            p_vout->yuv.yuv.p_gray16;
199     p_buffer_start =    p_vout->yuv.p_buffer;
200     p_offset_start =    p_vout->yuv.p_offset;
201     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
202                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
203
204     /*
205      * Perform conversion
206      */
207     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
208     for( i_y = 0; i_y < i_height; i_y++ )
209     {
210         /* Mark beginnning of line for possible later line copy, and initialize
211          * buffer */
212         p_pic_start =   p_pic;
213         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
214
215         /* Do YUV conversion to buffer - YUV picture is always formed of 16
216          * pixels wide blocks */
217         for( i_x = i_width / 16; i_x--;  )
218         {
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             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
227         }
228
229         /* Do horizontal and vertical scaling */
230         SCALE_WIDTH;
231         SCALE_HEIGHT(400, 2);
232     }
233 }
234
235 /*****************************************************************************
236  * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
237  *****************************************************************************/
238 void ConvertYUV420RGB16( YUV_ARGS_16BPP )
239 {
240     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
241     int         i_vertical_scaling;                 /* vertical scaling type */
242     int         i_x, i_y;                 /* horizontal and vertical indexes */
243     int         i_scale_count;                       /* scale modulo counter */
244     int         i_uval, i_vval;                           /* U and V samples */
245     int         i_red, i_green, i_blue;          /* U and V modified samples */
246     int         i_chroma_width;                              /* chroma width */
247     u16 *       p_yuv;                              /* base conversion table */
248     u16 *       p_ybase;                     /* Y dependant conversion table */
249     u16 *       p_pic_start;       /* beginning of the current line for copy */
250     u16 *       p_buffer_start;                   /* conversion buffer start */
251     u16 *       p_buffer;                       /* conversion buffer pointer */
252     int *       p_offset_start;                        /* offset array start */
253     int *       p_offset;                            /* offset array pointer */
254
255     /*
256      * Initialize some values  - i_pic_line_width will store the line skip
257      */
258     i_pic_line_width -= i_pic_width;
259     i_chroma_width =    i_width / 2;
260     p_yuv =             p_vout->yuv.yuv.p_rgb16;
261     p_buffer_start =    p_vout->yuv.p_buffer;
262     p_offset_start =    p_vout->yuv.p_offset;
263     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
264                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
265
266     /*
267      * Perform conversion
268      */
269     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
270     for( i_y = 0; i_y < i_height; i_y++ )
271     {
272         /* Mark beginnning of line for possible later line copy, and initialize
273          * buffer */
274         p_pic_start =   p_pic;
275         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
276
277         /* Do YUV conversion to buffer - YUV picture is always formed of 16
278          * pixels wide blocks */
279         for( i_x = i_width / 16; i_x--;  )
280         {
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             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
289         }
290
291         /* Do horizontal and vertical scaling */
292         SCALE_WIDTH;
293         SCALE_HEIGHT(420, 2);
294     }
295 }
296
297 /*****************************************************************************
298  * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
299  *****************************************************************************/
300 void ConvertYUV422RGB16( YUV_ARGS_16BPP )
301 {
302     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
303     int         i_vertical_scaling;                 /* vertical scaling type */
304     int         i_x, i_y;                 /* horizontal and vertical indexes */
305     int         i_scale_count;                       /* scale modulo counter */
306     int         i_uval, i_vval;                           /* U and V samples */
307     int         i_red, i_green, i_blue;          /* U and V modified samples */
308     int         i_chroma_width;                              /* chroma width */
309     u16 *       p_yuv;                              /* base conversion table */
310     u16 *       p_ybase;                     /* Y dependant conversion table */
311     u16 *       p_pic_start;       /* beginning of the current line for copy */
312     u16 *       p_buffer_start;                   /* conversion buffer start */
313     u16 *       p_buffer;                       /* conversion buffer pointer */
314     int *       p_offset_start;                        /* offset array start */
315     int *       p_offset;                            /* offset array pointer */
316
317     /*
318      * Initialize some values  - i_pic_line_width will store the line skip
319      */
320     i_pic_line_width -= i_pic_width;
321     i_chroma_width =    i_width / 2;
322     p_yuv =             p_vout->yuv.yuv.p_rgb16;
323     p_buffer_start =    p_vout->yuv.p_buffer;
324     p_offset_start =    p_vout->yuv.p_offset;
325     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
326                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
327
328     /*
329      * Perform conversion
330      */
331     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
332     for( i_y = 0; i_y < i_height; i_y++ )
333     {
334         /* Mark beginnning of line for possible later line copy, and initialize
335          * buffer */
336         p_pic_start =   p_pic;
337         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
338
339         /* Do YUV conversion to buffer - YUV picture is always formed of 16
340          * pixels wide blocks */
341         for( i_x = i_width / 16; i_x--;  )
342         {
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             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
351         }
352
353         /* Do horizontal and vertical scaling */
354         SCALE_WIDTH;
355         SCALE_HEIGHT(422, 2);
356     }
357 }
358
359 /*****************************************************************************
360  * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
361  *****************************************************************************/
362 void ConvertYUV444RGB16( YUV_ARGS_16BPP )
363 {
364     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
365     int         i_vertical_scaling;                 /* vertical scaling type */
366     int         i_x, i_y;                 /* horizontal and vertical indexes */
367     int         i_scale_count;                       /* scale modulo counter */
368     int         i_uval, i_vval;                           /* U and V samples */
369     int         i_red, i_green, i_blue;          /* U and V modified samples */
370     int         i_chroma_width;                    /* chroma width, not used */
371     u16 *       p_yuv;                              /* base conversion table */
372     u16 *       p_ybase;                     /* Y dependant conversion table */
373     u16 *       p_pic_start;       /* beginning of the current line for copy */
374     u16 *       p_buffer_start;                   /* conversion buffer start */
375     u16 *       p_buffer;                       /* conversion buffer pointer */
376     int *       p_offset_start;                        /* offset array start */
377     int *       p_offset;                            /* offset array pointer */
378
379     /*
380      * Initialize some values  - i_pic_line_width will store the line skip
381      */
382     i_pic_line_width -= i_pic_width;
383     p_yuv =             p_vout->yuv.yuv.p_rgb16;
384     p_buffer_start =    p_vout->yuv.p_buffer;
385     p_offset_start =    p_vout->yuv.p_offset;
386     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
387                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
388
389     /*
390      * Perform conversion
391      */
392     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
393     for( i_y = 0; i_y < i_height; i_y++ )
394     {
395         /* Mark beginnning of line for possible later line copy, and initialize
396          * buffer */
397         p_pic_start =   p_pic;
398         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
399
400         /* Do YUV conversion to buffer - YUV picture is always formed of 16
401          * pixels wide blocks */
402         for( i_x = i_width / 16; i_x--;  )
403         {
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             CONVERT_YUV_PIXEL(2);  CONVERT_YUV_PIXEL(2);
412         }
413
414         /* Do horizontal and vertical scaling */
415         SCALE_WIDTH;
416         SCALE_HEIGHT(444, 2);
417     }
418 }
419
420 /*****************************************************************************
421  * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 2 Bpp
422  *****************************************************************************/
423 void ConvertY4Gray24( YUV_ARGS_24BPP )
424 {
425     intf_ErrMsg( "yuv error: unhandled function, grayscale, bpp = 24" );
426 }
427
428 /*****************************************************************************
429  * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 2 Bpp
430  *****************************************************************************/
431 void ConvertYUV420RGB24( YUV_ARGS_24BPP )
432 {
433     intf_ErrMsg( "yuv error: unhandled function, chroma = 420, bpp = 24" );
434 }
435
436 /*****************************************************************************
437  * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 2 Bpp
438  *****************************************************************************/
439 void ConvertYUV422RGB24( YUV_ARGS_24BPP )
440 {
441     intf_ErrMsg( "yuv error: unhandled function, chroma = 422, bpp = 24" );
442 }
443
444 /*****************************************************************************
445  * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 2 Bpp
446  *****************************************************************************/
447 void ConvertYUV444RGB24( YUV_ARGS_24BPP )
448 {
449     intf_ErrMsg( "yuv error: unhandled function, chroma = 444, bpp = 24" );
450 }
451
452 /*****************************************************************************
453  * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
454  *****************************************************************************/
455 void ConvertY4Gray32( YUV_ARGS_32BPP )
456 {
457     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
458     int         i_vertical_scaling;                 /* vertical scaling type */
459     int         i_x, i_y;                 /* horizontal and vertical indexes */
460     int         i_scale_count;                       /* scale modulo counter */
461     int         i_chroma_width;                    /* chroma width, not used */
462     u32 *       p_gray;                             /* base conversion table */
463     u32 *       p_pic_start;       /* beginning of the current line for copy */
464     u32 *       p_buffer_start;                   /* conversion buffer start */
465     u32 *       p_buffer;                       /* conversion buffer pointer */
466     int *       p_offset_start;                        /* offset array start */
467     int *       p_offset;                            /* offset array pointer */
468
469     /*
470      * Initialize some values  - i_pic_line_width will store the line skip
471      */
472     i_pic_line_width -= i_pic_width;
473     p_gray =            p_vout->yuv.yuv.p_gray32;
474     p_buffer_start =    p_vout->yuv.p_buffer;
475     p_offset_start =    p_vout->yuv.p_offset;
476     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
477                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
478
479     /*
480      * Perform conversion
481      */
482     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
483     for( i_y = 0; i_y < i_height; i_y++ )
484     {
485         /* Mark beginnning of line for possible later line copy, and initialize
486          * buffer */
487         p_pic_start =   p_pic;
488         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
489
490         /* Do YUV conversion to buffer - YUV picture is always formed of 16
491          * pixels wide blocks */
492         for( i_x = i_width / 16; i_x--;  )
493         {
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             *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
502         }
503
504         /* Do horizontal and vertical scaling */
505         SCALE_WIDTH;
506         SCALE_HEIGHT(400, 4);
507     }
508 }
509
510 /*****************************************************************************
511  * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
512  *****************************************************************************/
513 void ConvertYUV420RGB32( YUV_ARGS_32BPP )
514 {
515     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
516     int         i_vertical_scaling;                 /* vertical scaling type */
517     int         i_x, i_y;                 /* horizontal and vertical indexes */
518     int         i_scale_count;                       /* scale modulo counter */
519     int         i_uval, i_vval;                           /* U and V samples */
520     int         i_red, i_green, i_blue;          /* U and V modified samples */
521     int         i_chroma_width;                              /* chroma width */
522     u32 *       p_yuv;                              /* base conversion table */
523     u32 *       p_ybase;                     /* Y dependant conversion table */
524     u32 *       p_pic_start;       /* beginning of the current line for copy */
525     u32 *       p_buffer_start;                   /* conversion buffer start */
526     u32 *       p_buffer;                       /* conversion buffer pointer */
527     int *       p_offset_start;                        /* offset array start */
528     int *       p_offset;                            /* offset array pointer */
529
530     /*
531      * Initialize some values  - i_pic_line_width will store the line skip
532      */
533     i_pic_line_width -= i_pic_width;
534     i_chroma_width =    i_width / 2;
535     p_yuv =             p_vout->yuv.yuv.p_rgb32;
536     p_buffer_start =    p_vout->yuv.p_buffer;
537     p_offset_start =    p_vout->yuv.p_offset;
538     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
539                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
540
541     /*
542      * Perform conversion
543      */
544     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
545     for( i_y = 0; i_y < i_height; i_y++ )
546     {
547         /* Mark beginnning of line for possible later line copy, and initialize
548          * buffer */
549         p_pic_start =   p_pic;
550         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
551
552         /* Do YUV conversion to buffer - YUV picture is always formed of 16
553          * pixels wide blocks */
554         for( i_x = i_width / 16; i_x--;  )
555         {
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             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
564         }
565
566         /* Do horizontal and vertical scaling */
567         SCALE_WIDTH;
568         SCALE_HEIGHT(420, 4);
569     }
570 }
571
572 /*****************************************************************************
573  * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
574  *****************************************************************************/
575 void ConvertYUV422RGB32( YUV_ARGS_32BPP )
576 {
577     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
578     int         i_vertical_scaling;                 /* vertical scaling type */
579     int         i_x, i_y;                 /* horizontal and vertical indexes */
580     int         i_scale_count;                       /* scale modulo counter */
581     int         i_uval, i_vval;                           /* U and V samples */
582     int         i_red, i_green, i_blue;          /* U and V modified samples */
583     int         i_chroma_width;                              /* chroma width */
584     u32 *       p_yuv;                              /* base conversion table */
585     u32 *       p_ybase;                     /* Y dependant conversion table */
586     u32 *       p_pic_start;       /* beginning of the current line for copy */
587     u32 *       p_buffer_start;                   /* conversion buffer start */
588     u32 *       p_buffer;                       /* conversion buffer pointer */
589     int *       p_offset_start;                        /* offset array start */
590     int *       p_offset;                            /* offset array pointer */
591
592     /*
593      * Initialize some values  - i_pic_line_width will store the line skip
594      */
595     i_pic_line_width -= i_pic_width;
596     i_chroma_width =    i_width / 2;
597     p_yuv =             p_vout->yuv.yuv.p_rgb32;
598     p_buffer_start =    p_vout->yuv.p_buffer;
599     p_offset_start =    p_vout->yuv.p_offset;
600     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
601                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
602
603     /*
604      * Perform conversion
605      */
606     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
607     for( i_y = 0; i_y < i_height; i_y++ )
608     {
609         /* Mark beginnning of line for possible later line copy, and initialize
610          * buffer */
611         p_pic_start =   p_pic;
612         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
613
614         /* Do YUV conversion to buffer - YUV picture is always formed of 16
615          * pixels wide blocks */
616         for( i_x = i_width / 16; i_x--;  )
617         {
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             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
626         }
627
628         /* Do horizontal and vertical scaling */
629         SCALE_WIDTH;
630         SCALE_HEIGHT(422, 4);
631     }
632 }
633
634 /*****************************************************************************
635  * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
636  *****************************************************************************/
637 void ConvertYUV444RGB32( YUV_ARGS_32BPP )
638 {
639     boolean_t   b_horizontal_scaling;             /* horizontal scaling type */
640     int         i_vertical_scaling;                 /* vertical scaling type */
641     int         i_x, i_y;                 /* horizontal and vertical indexes */
642     int         i_scale_count;                       /* scale modulo counter */
643     int         i_uval, i_vval;                           /* U and V samples */
644     int         i_red, i_green, i_blue;          /* U and V modified samples */
645     int         i_chroma_width;                    /* chroma width, not used */
646     u32 *       p_yuv;                              /* base conversion table */
647     u32 *       p_ybase;                     /* Y dependant conversion table */
648     u32 *       p_pic_start;       /* beginning of the current line for copy */
649     u32 *       p_buffer_start;                   /* conversion buffer start */
650     u32 *       p_buffer;                       /* conversion buffer pointer */
651     int *       p_offset_start;                        /* offset array start */
652     int *       p_offset;                            /* offset array pointer */
653
654     /*
655      * Initialize some values  - i_pic_line_width will store the line skip
656      */
657     i_pic_line_width -= i_pic_width;
658     p_yuv =             p_vout->yuv.yuv.p_rgb32;
659     p_buffer_start =    p_vout->yuv.p_buffer;
660     p_offset_start =    p_vout->yuv.p_offset;
661     SetOffset( i_width, i_height, i_pic_width, i_pic_height,
662                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
663
664     /*
665      * Perform conversion
666      */
667     i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
668     for( i_y = 0; i_y < i_height; i_y++ )
669     {
670         /* Mark beginnning of line for possible later line copy, and initialize
671          * buffer */
672         p_pic_start =   p_pic;
673         p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;
674
675         /* Do YUV conversion to buffer - YUV picture is always formed of 16
676          * pixels wide blocks */
677         for( i_x = i_width / 16; i_x--;  )
678         {
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             CONVERT_YUV_PIXEL(4);  CONVERT_YUV_PIXEL(4);
687         }
688
689         /* Do horizontal and vertical scaling */
690         SCALE_WIDTH;
691         SCALE_HEIGHT(444, 4);
692     }
693 }
694