access_http: fix unbalanced quotes
[vlc/solaris.git] / modules / video_chroma / i420_rgb.h
blob66171fbeee5ad0e40355391250d0c691739100b9
1 /*****************************************************************************
2 * i420_rgb.h : YUV to bitmap RGB conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2004 the VideoLAN team
5 * $Id$
7 * Authors: Samuel Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /** Number of entries in RGB palette/colormap */
25 #define CMAP_RGB2_SIZE 256
27 /**
28 * filter_sys_t: chroma method descriptor
30 * This structure is part of the chroma transformation descriptor, it
31 * describes the yuv2rgb specific properties.
33 struct filter_sys_t
35 uint8_t *p_buffer;
36 int *p_offset;
38 #ifdef MODULE_NAME_IS_i420_rgb
39 /**< Pre-calculated conversion tables */
40 void *p_base; /**< base for all conversion tables */
41 uint8_t *p_rgb8; /**< RGB 8 bits table */
42 uint16_t *p_rgb16; /**< RGB 16 bits table */
43 uint32_t *p_rgb32; /**< RGB 32 bits table */
45 /**< To get RGB value for palette entry i, use (p_rgb_r[i], p_rgb_g[i],
46 p_rgb_b[i]). Note these are 16 bits per pixel. For 8bpp entries,
47 shift right 8 bits.
49 uint16_t p_rgb_r[CMAP_RGB2_SIZE]; /**< Red values of palette */
50 uint16_t p_rgb_g[CMAP_RGB2_SIZE]; /**< Green values of palette */
51 uint16_t p_rgb_b[CMAP_RGB2_SIZE]; /**< Blue values of palette */
52 #endif
55 /*****************************************************************************
56 * Prototypes
57 *****************************************************************************/
58 #ifdef MODULE_NAME_IS_i420_rgb
59 void I420_RGB8 ( filter_t *, picture_t *, picture_t * );
60 void I420_RGB16_dither ( filter_t *, picture_t *, picture_t * );
61 void I420_RGB16 ( filter_t *, picture_t *, picture_t * );
62 void I420_RGB32 ( filter_t *, picture_t *, picture_t * );
63 #else // if defined(MODULE_NAME_IS_i420_rgb_mmx)
64 void I420_R5G5B5 ( filter_t *, picture_t *, picture_t * );
65 void I420_R5G6B5 ( filter_t *, picture_t *, picture_t * );
66 void I420_A8R8G8B8 ( filter_t *, picture_t *, picture_t * );
67 void I420_R8G8B8A8 ( filter_t *, picture_t *, picture_t * );
68 void I420_B8G8R8A8 ( filter_t *, picture_t *, picture_t * );
69 void I420_A8B8G8R8 ( filter_t *, picture_t *, picture_t * );
70 #endif
72 /*****************************************************************************
73 * CONVERT_*_PIXEL: pixel conversion macros
74 *****************************************************************************
75 * These conversion routines are used by YUV conversion functions.
76 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
77 * which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
78 * CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
79 *****************************************************************************/
80 #define CONVERT_Y_PIXEL( BPP ) \
81 /* Only Y sample is present */ \
82 p_ybase = p_yuv + *p_y++; \
83 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
84 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
85 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
87 #define CONVERT_YUV_PIXEL( BPP ) \
88 /* Y, U and V samples are present */ \
89 i_uval = *p_u++; \
90 i_vval = *p_v++; \
91 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
92 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
93 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
94 CONVERT_Y_PIXEL( BPP ) \
96 #define CONVERT_Y_PIXEL_DITHER( BPP ) \
97 /* Only Y sample is present */ \
98 p_ybase = p_yuv + *p_y++; \
99 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128+p_dither[i_real_y])>>SHIFT) + i_red] | \
100 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128+p_dither[i_real_y])>>SHIFT) \
101 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128+p_dither[i_real_y])>>SHIFT) + i_blue];
103 #define CONVERT_YUV_PIXEL_DITHER( BPP ) \
104 /* Y, U and V samples are present */ \
105 i_uval = *p_u++; \
106 i_vval = *p_v++; \
107 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
108 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
109 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
110 CONVERT_Y_PIXEL_DITHER( BPP ) \
112 #define CONVERT_4YUV_PIXEL( CHROMA ) \
113 *p_pic++ = p_lookup[ \
114 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
115 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
116 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
117 *p_pic++ = p_lookup[ \
118 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
119 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
120 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
121 *p_pic++ = p_lookup[ \
122 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
123 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
124 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
125 *p_pic++ = p_lookup[ \
126 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
127 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
128 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
130 #define CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
131 *p_pic++ = p_lookup[ \
132 ( ((*p_y + dither10[i_real_y]) >> 4) << 7) \
133 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
134 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
135 p_y += *p_offset++; \
136 p_u += *p_offset; \
137 p_v += *p_offset++; \
138 *p_pic++ = p_lookup[ \
139 ( ((*p_y + dither11[i_real_y]) >> 4) << 7) \
140 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
141 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
142 p_y += *p_offset++; \
143 p_u += *p_offset; \
144 p_v += *p_offset++; \
145 *p_pic++ = p_lookup[ \
146 ( ((*p_y + dither12[i_real_y]) >> 4) << 7) \
147 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
148 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
149 p_y += *p_offset++; \
150 p_u += *p_offset; \
151 p_v += *p_offset++; \
152 *p_pic++ = p_lookup[ \
153 ( ((*p_y + dither13[i_real_y]) >> 4) << 7) \
154 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
155 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
156 p_y += *p_offset++; \
157 p_u += *p_offset; \
158 p_v += *p_offset++; \
160 /*****************************************************************************
161 * SCALE_WIDTH: scale a line horizontally
162 *****************************************************************************
163 * This macro scales a line using rendering buffer and offset array. It works
164 * for 1, 2 and 4 Bpp.
165 *****************************************************************************/
166 #define SCALE_WIDTH \
167 if( b_hscale ) \
169 /* Horizontal scaling, conversion has been done to buffer. \
170 * Rewind buffer and offset, then copy and scale line */ \
171 p_buffer = p_buffer_start; \
172 p_offset = p_offset_start; \
173 for( i_x = p_filter->fmt_out.video.i_width / 16; i_x--; ) \
175 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
176 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
177 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
178 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
179 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
180 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
181 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
182 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
183 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
184 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
185 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
186 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
187 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
188 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
189 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
190 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
192 for( i_x = p_filter->fmt_out.video.i_width & 15; i_x--; ) \
194 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
196 p_pic = (void*)((uint8_t*)p_pic + i_right_margin ); \
198 else \
200 /* No scaling, conversion has been done directly in picture memory. \
201 * Increment of picture pointer to end of line is still needed */ \
202 p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch ); \
205 /*****************************************************************************
206 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
207 *****************************************************************************
208 * This macro scales a line using an offset array.
209 *****************************************************************************/
210 #define SCALE_WIDTH_DITHER( CHROMA ) \
211 if( b_hscale ) \
213 /* Horizontal scaling - we can't use a buffer due to dithering */ \
214 p_offset = p_offset_start; \
215 for( i_x = p_filter->fmt_out.video.i_width / 16; i_x--; ) \
217 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
218 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
219 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
220 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
223 else \
225 for( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; ) \
227 CONVERT_4YUV_PIXEL( CHROMA ) \
228 CONVERT_4YUV_PIXEL( CHROMA ) \
229 CONVERT_4YUV_PIXEL( CHROMA ) \
230 CONVERT_4YUV_PIXEL( CHROMA ) \
233 /* Increment of picture pointer to end of line is still needed */ \
234 p_pic = (void*)((uint8_t*)p_pic + i_right_margin ); \
236 /* Increment the Y coordinate in the matrix, modulo 4 */ \
237 i_real_y = (i_real_y + 1) & 0x3; \
239 /*****************************************************************************
240 * SCALE_HEIGHT: handle vertical scaling
241 *****************************************************************************
242 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
243 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
244 * and 4 Bpp.
245 *****************************************************************************/
246 #define SCALE_HEIGHT( CHROMA, BPP ) \
247 /* If line is odd, rewind 4:2:0 U and V samples */ \
248 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
250 p_u -= i_chroma_width; \
251 p_v -= i_chroma_width; \
254 /* \
255 * Handle vertical scaling. The current line can be copied or next one \
256 * can be ignored. \
257 */ \
258 switch( i_vscale ) \
260 case -1: /* vertical scaling factor is < 1 */ \
261 while( (i_scale_count -= p_filter->fmt_out.video.i_height) > 0 ) \
263 /* Height reduction: skip next source line */ \
264 p_y += p_filter->fmt_in.video.i_width; \
265 i_y++; \
266 if( (CHROMA == 420) || (CHROMA == 422) ) \
268 if( i_y & 0x1 ) \
270 p_u += i_chroma_width; \
271 p_v += i_chroma_width; \
274 else if( CHROMA == 444 ) \
276 p_u += p_filter->fmt_in.video.i_width; \
277 p_v += p_filter->fmt_in.video.i_width; \
280 i_scale_count += p_filter->fmt_in.video.i_height; \
281 break; \
282 case 1: /* vertical scaling factor is > 1 */ \
283 while( (i_scale_count -= p_filter->fmt_in.video.i_height) > 0 ) \
285 /* Height increment: copy previous picture line */ \
286 vlc_memcpy( p_pic, p_pic_start, p_filter->fmt_out.video.i_width * BPP ); \
287 p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch ); \
289 i_scale_count += p_filter->fmt_out.video.i_height; \
290 break; \
293 /*****************************************************************************
294 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
295 *****************************************************************************
296 * This macro handles vertical scaling for a picture. CHROMA may be 420,
297 * 422 or 444 for RGB conversion, or 400 for gray conversion.
298 *****************************************************************************/
299 #define SCALE_HEIGHT_DITHER( CHROMA ) \
301 /* If line is odd, rewind 4:2:0 U and V samples */ \
302 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
304 p_u -= i_chroma_width; \
305 p_v -= i_chroma_width; \
308 /* \
309 * Handle vertical scaling. The current line can be copied or next one \
310 * can be ignored. \
311 */ \
313 switch( i_vscale ) \
315 case -1: /* vertical scaling factor is < 1 */ \
316 while( (i_scale_count -= p_filter->fmt_out.video.i_height) > 0 ) \
318 /* Height reduction: skip next source line */ \
319 p_y += p_filter->fmt_in.video.i_width; \
320 i_y++; \
321 if( (CHROMA == 420) || (CHROMA == 422) ) \
323 if( i_y & 0x1 ) \
325 p_u += i_chroma_width; \
326 p_v += i_chroma_width; \
329 else if( CHROMA == 444 ) \
331 p_u += p_filter->fmt_in.video.i_width; \
332 p_v += p_filter->fmt_in.video.i_width; \
335 i_scale_count += p_filter->fmt_in.video.i_height; \
336 break; \
337 case 1: /* vertical scaling factor is > 1 */ \
338 while( (i_scale_count -= p_filter->fmt_in.video.i_height) > 0 ) \
340 p_y -= p_filter->fmt_in.video.i_width; \
341 p_u -= i_chroma_width; \
342 p_v -= i_chroma_width; \
343 SCALE_WIDTH_DITHER( CHROMA ); \
345 i_scale_count += p_filter->fmt_out.video.i_height; \
346 break; \