1
/*****************************************************************************
2
* i420_rgb.h : YUV to bitmap RGB conversion module for vlc
3
*****************************************************************************
4
* Copyright (C) 2000, 2004 VideoLAN
5
* $Id: i420_rgb.h 7194 2004-03-29 19:57:07Z fenrir $
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22
*****************************************************************************/
24
/** Number of entries in RGB palette/colormap */
25
#define CMAP_RGB2_SIZE 256
28
* chroma_sys_t: chroma method descriptor
30
* This structure is part of the chroma transformation descriptor, it
31
* describes the yuv2rgb specific properties.
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,
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 */
55
/*****************************************************************************
57
*****************************************************************************/
58
#ifdef MODULE_NAME_IS_i420_rgb
59
void E_(I420_RGB8) ( vout_thread_t *, picture_t *, picture_t * );
60
void E_(I420_RGB16_dither) ( vout_thread_t *, picture_t *, picture_t * );
62
void E_(I420_RGB16) ( vout_thread_t *, picture_t *, picture_t * );
63
void E_(I420_RGB32) ( vout_thread_t *, picture_t *, picture_t * );
65
/*****************************************************************************
66
* CONVERT_*_PIXEL: pixel conversion macros
67
*****************************************************************************
68
* These conversion routines are used by YUV conversion functions.
69
* conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
70
* which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
71
* CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
72
*****************************************************************************/
73
#define CONVERT_Y_PIXEL( BPP ) \
74
/* Only Y sample is present */ \
75
p_ybase = p_yuv + *p_y++; \
76
*p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
77
p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
78
+ i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
80
#define CONVERT_YUV_PIXEL( BPP ) \
81
/* Y, U and V samples are present */ \
84
i_red = (V_RED_COEF * i_vval) >> SHIFT; \
85
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
86
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
87
CONVERT_Y_PIXEL( BPP ) \
89
#define CONVERT_Y_PIXEL_DITHER( BPP ) \
90
/* Only Y sample is present */ \
91
p_ybase = p_yuv + *p_y++; \
92
*p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128+p_dither[i_real_y])>>SHIFT) + i_red] | \
93
p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128+p_dither[i_real_y])>>SHIFT) \
94
+ i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128+p_dither[i_real_y])>>SHIFT) + i_blue];
96
#define CONVERT_YUV_PIXEL_DITHER( BPP ) \
97
/* Y, U and V samples are present */ \
100
i_red = (V_RED_COEF * i_vval) >> SHIFT; \
101
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
102
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
103
CONVERT_Y_PIXEL_DITHER( BPP ) \
105
#define CONVERT_4YUV_PIXEL( CHROMA ) \
106
*p_pic++ = p_lookup[ \
107
(((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
108
+ ((*p_u + dither20[i_real_y]) >> 5) * 9 \
109
+ ((*p_v + dither20[i_real_y]) >> 5) ]; \
110
*p_pic++ = p_lookup[ \
111
(((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
112
+ ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
113
+ ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
114
*p_pic++ = p_lookup[ \
115
(((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
116
+ ((*p_u + dither22[i_real_y]) >> 5) * 9 \
117
+ ((*p_v + dither22[i_real_y]) >> 5) ]; \
118
*p_pic++ = p_lookup[ \
119
(((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
120
+ ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
121
+ ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
123
#define CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
124
*p_pic++ = p_lookup[ \
125
( ((*p_y + dither10[i_real_y]) >> 4) << 7) \
126
+ ((*p_u + dither20[i_real_y]) >> 5) * 9 \
127
+ ((*p_v + dither20[i_real_y]) >> 5) ]; \
128
p_y += *p_offset++; \
130
p_v += *p_offset++; \
131
*p_pic++ = p_lookup[ \
132
( ((*p_y + dither11[i_real_y]) >> 4) << 7) \
133
+ ((*p_u + dither21[i_real_y]) >> 5) * 9 \
134
+ ((*p_v + dither21[i_real_y]) >> 5) ]; \
135
p_y += *p_offset++; \
137
p_v += *p_offset++; \
138
*p_pic++ = p_lookup[ \
139
( ((*p_y + dither12[i_real_y]) >> 4) << 7) \
140
+ ((*p_u + dither22[i_real_y]) >> 5) * 9 \
141
+ ((*p_v + dither22[i_real_y]) >> 5) ]; \
142
p_y += *p_offset++; \
144
p_v += *p_offset++; \
145
*p_pic++ = p_lookup[ \
146
( ((*p_y + dither13[i_real_y]) >> 4) << 7) \
147
+ ((*p_u + dither23[i_real_y]) >> 5) * 9 \
148
+ ((*p_v + dither23[i_real_y]) >> 5) ]; \
149
p_y += *p_offset++; \
151
p_v += *p_offset++; \
153
/*****************************************************************************
154
* SCALE_WIDTH: scale a line horizontally
155
*****************************************************************************
156
* This macro scales a line using rendering buffer and offset array. It works
157
* for 1, 2 and 4 Bpp.
158
*****************************************************************************/
159
#define SCALE_WIDTH \
162
/* Horizontal scaling, conversion has been done to buffer. \
163
* Rewind buffer and offset, then copy and scale line */ \
164
p_buffer = p_buffer_start; \
165
p_offset = p_offset_start; \
166
for( i_x = p_vout->output.i_width / 16; i_x--; ) \
168
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
169
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
170
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
171
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
172
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
173
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
174
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
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++; \
185
for( i_x = p_vout->output.i_width & 15; i_x--; ) \
187
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
189
p_pic = (void*)((uint8_t*)p_pic + i_right_margin ); \
193
/* No scaling, conversion has been done directly in picture memory. \
194
* Increment of picture pointer to end of line is still needed */ \
195
p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch ); \
198
/*****************************************************************************
199
* SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
200
*****************************************************************************
201
* This macro scales a line using an offset array.
202
*****************************************************************************/
203
#define SCALE_WIDTH_DITHER( CHROMA ) \
206
/* Horizontal scaling - we can't use a buffer due to dithering */ \
207
p_offset = p_offset_start; \
208
for( i_x = p_vout->output.i_width / 16; i_x--; ) \
210
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
211
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
212
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
213
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
218
for( i_x = p_vout->render.i_width / 16; i_x--; ) \
220
CONVERT_4YUV_PIXEL( CHROMA ) \
221
CONVERT_4YUV_PIXEL( CHROMA ) \
222
CONVERT_4YUV_PIXEL( CHROMA ) \
223
CONVERT_4YUV_PIXEL( CHROMA ) \
226
/* Increment of picture pointer to end of line is still needed */ \
227
p_pic = (void*)((uint8_t*)p_pic + i_right_margin ); \
229
/* Increment the Y coordinate in the matrix, modulo 4 */ \
230
i_real_y = (i_real_y + 1) & 0x3; \
232
/*****************************************************************************
233
* SCALE_HEIGHT: handle vertical scaling
234
*****************************************************************************
235
* This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
236
* 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
238
*****************************************************************************/
239
#define SCALE_HEIGHT( CHROMA, BPP ) \
240
/* If line is odd, rewind 4:2:0 U and V samples */ \
241
if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
243
p_u -= i_chroma_width; \
244
p_v -= i_chroma_width; \
248
* Handle vertical scaling. The current line can be copied or next one \
253
case -1: /* vertical scaling factor is < 1 */ \
254
while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
256
/* Height reduction: skip next source line */ \
257
p_y += p_vout->render.i_width; \
259
if( (CHROMA == 420) || (CHROMA == 422) ) \
263
p_u += i_chroma_width; \
264
p_v += i_chroma_width; \
267
else if( CHROMA == 444 ) \
269
p_u += p_vout->render.i_width; \
270
p_v += p_vout->render.i_width; \
273
i_scale_count += p_vout->render.i_height; \
275
case 1: /* vertical scaling factor is > 1 */ \
276
while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
278
/* Height increment: copy previous picture line */ \
279
p_vout->p_vlc->pf_memcpy( p_pic, p_pic_start, \
280
p_vout->output.i_width * BPP ); \
281
p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch ); \
283
i_scale_count += p_vout->output.i_height; \
287
/*****************************************************************************
288
* SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
289
*****************************************************************************
290
* This macro handles vertical scaling for a picture. CHROMA may be 420,
291
* 422 or 444 for RGB conversion, or 400 for gray conversion.
292
*****************************************************************************/
293
#define SCALE_HEIGHT_DITHER( CHROMA ) \
295
/* If line is odd, rewind 4:2:0 U and V samples */ \
296
if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
298
p_u -= i_chroma_width; \
299
p_v -= i_chroma_width; \
303
* Handle vertical scaling. The current line can be copied or next one \
309
case -1: /* vertical scaling factor is < 1 */ \
310
while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
312
/* Height reduction: skip next source line */ \
313
p_y += p_vout->render.i_width; \
315
if( (CHROMA == 420) || (CHROMA == 422) ) \
319
p_u += i_chroma_width; \
320
p_v += i_chroma_width; \
323
else if( CHROMA == 444 ) \
325
p_u += p_vout->render.i_width; \
326
p_v += p_vout->render.i_width; \
329
i_scale_count += p_vout->render.i_height; \
331
case 1: /* vertical scaling factor is > 1 */ \
332
while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
334
p_y -= p_vout->render.i_width; \
335
p_u -= i_chroma_width; \
336
p_v -= i_chroma_width; \
337
SCALE_WIDTH_DITHER( CHROMA ); \
339
i_scale_count += p_vout->output.i_height; \