1 /*****************************************************************************
2 * video_yuv.c: YUV transformation functions
4 *****************************************************************************
5 * Provides functions to perform the YUV conversion. The functions provided here
6 * are a complete and portable C implementation, and may be replaced in certain
7 * case by optimized functions.
8 *****************************************************************************/
10 /*****************************************************************************
12 *****************************************************************************/
21 #include "vlc_thread.h"
23 #include "video_output.h"
24 #include "video_yuv.h"
27 /*****************************************************************************
29 *****************************************************************************/
31 /* Color masks for different color depths - 8bpp masks can be choosen, since
32 * colormaps instead of hardware-defined colors are used. */
34 #define RED_8BPP_MASK 0xe0
35 #define GREEN_8BPP_MASK 0x1c
36 #define BLUE_8BPP_MASK 0x03
38 #define RED_15BPP_MASK 0xf800
39 #define GREEN_15BPP_MASK 0x03e0
40 #define BLUE_15BPP_MASK 0x001f
42 #define RED_16BPP_MASK 0xf800
43 #define GREEN_16BPP_MASK 0x07e0
44 #define BLUE_16BPP_MASK 0x001f
46 #define RED_24BPP_MASK 0xff0000
47 #define GREEN_24BPP_MASK 0x00ff00
48 #define BLUE_24BPP_MASK 0x0000ff
50 /* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
52 const int MATRIX_COEFFICIENTS_TABLE[8][4] =
54 {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
55 {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
56 {104597, 132201, 25675, 53279}, /* unspecified */
57 {104597, 132201, 25675, 53279}, /* reserved */
58 {104448, 132798, 24759, 53109}, /* FCC */
59 {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
60 {104597, 132201, 25675, 53279}, /* SMPTE 170M */
61 {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
64 /* Margins and offsets in conversion tables - Margins are used in case a RGB
65 * RGB conversion would give a value outside the 0-255 range. Offsets have been
66 * calculated to avoid using the same cache line for 2 tables. conversion tables
67 * are 2*MARGIN + 256 long and stores pixels.*/
68 #define RED_MARGIN 178
69 #define GREEN_MARGIN 135
70 #define BLUE_MARGIN 224
71 #define RED_OFFSET 1501 /* 1323 to 1935 */
72 #define GREEN_OFFSET 135 /* 0 to 526 */
73 #define BLUE_OFFSET 818 /* 594 to 1298 */
74 #define RGB_TABLE_SIZE 1935 /* total table size */
76 #define GRAY_MARGIN 384
77 #define GRAY_TABLE_SIZE 1024 /* total table size */
79 #define PALETTE_TABLE_SIZE 2176 /* YUV -> 8bpp palette lookup table */
83 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
84 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
85 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
86 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
88 /*****************************************************************************
90 *****************************************************************************/
91 static void SetGammaTable ( int *pi_table, double f_gamma );
92 static void SetYUV ( vout_thread_t *p_vout );
93 static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height,
94 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
96 static void ConvertY4Gray8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
97 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
98 int i_matrix_coefficients );
99 static void ConvertY4Gray16 ( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
100 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
101 int i_matrix_coefficients );
102 static void ConvertY4Gray24 ( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
103 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
104 int i_matrix_coefficients );
105 static void ConvertY4Gray32 ( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
106 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
107 int i_matrix_coefficients );
108 static void ConvertYUV420RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
109 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
110 int i_matrix_coefficients );
111 static void ConvertYUV422RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
112 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
113 int i_matrix_coefficients );
114 static void ConvertYUV444RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
115 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
116 int i_matrix_coefficients );
117 static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
118 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
119 int i_matrix_coefficients );
120 static void ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
121 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
122 int i_matrix_coefficients );
123 static void ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
124 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
125 int i_matrix_coefficients );
126 static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
127 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
128 int i_matrix_coefficients );
129 static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
130 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
131 int i_matrix_coefficients );
132 static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
133 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
134 int i_matrix_coefficients );
135 static void ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
136 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
137 int i_matrix_coefficients );
138 static void ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
139 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
140 int i_matrix_coefficients );
141 static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
142 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
143 int i_matrix_coefficients );
145 /*****************************************************************************
146 * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel conversion blocks
147 *****************************************************************************
148 * These conversion routines are used by YUV conversion functions.
149 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
150 * which is also modified.
151 *****************************************************************************/
152 #define CONVERT_Y_PIXEL( BPP ) \
153 /* Only Y sample is present */ \
154 p_ybase = p_yuv + *p_y++; \
155 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
156 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
157 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
159 #define CONVERT_YUV_PIXEL( BPP ) \
160 /* Y, U and V samples are present */ \
163 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
164 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
165 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
166 CONVERT_Y_PIXEL( BPP ) \
168 /*****************************************************************************
169 * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp
170 *****************************************************************************
171 * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
172 *****************************************************************************/
173 #define CONVERT_4YUV_PIXELS( CHROMA ) \
174 *p_pic++ = p_lookup[ \
175 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
176 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
177 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
178 *p_pic++ = p_lookup[ \
179 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
180 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
181 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
182 *p_pic++ = p_lookup[ \
183 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
184 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
185 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
186 *p_pic++ = p_lookup[ \
187 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
188 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
189 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
191 #define CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
192 *p_pic++ = p_lookup[ \
193 (((*p_y + dither10[i_real_y]) >> 4) << 7) \
194 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
195 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
196 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
198 p_u += *p_offset & b_jump_uv; \
199 p_v += *p_offset++ & b_jump_uv; \
200 *p_pic++ = p_lookup[ \
201 (((*p_y + dither11[i_real_y]) >> 4) << 7) \
202 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
203 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
204 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
206 p_u += *p_offset & b_jump_uv; \
207 p_v += *p_offset++ & b_jump_uv; \
208 *p_pic++ = p_lookup[ \
209 (((*p_y + dither12[i_real_y]) >> 4) << 7) \
210 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
211 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
212 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
214 p_u += *p_offset & b_jump_uv; \
215 p_v += *p_offset++ & b_jump_uv; \
216 *p_pic++ = p_lookup[ \
217 (((*p_y + dither13[i_real_y]) >> 4) << 7) \
218 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
219 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
220 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
222 p_u += *p_offset & b_jump_uv; \
223 p_v += *p_offset++ & b_jump_uv; \
225 /*****************************************************************************
226 * SCALE_WIDTH: scale a line horizontally
227 *****************************************************************************
228 * This macro scales a line using rendering buffer and offset array. It works
229 * for 1, 2 and 4 Bpp.
230 *****************************************************************************/
231 #define SCALE_WIDTH \
232 if( b_horizontal_scaling ) \
234 /* Horizontal scaling, conversion has been done to buffer. \
235 * Rewind buffer and offset, then copy and scale line */ \
236 p_buffer = p_buffer_start; \
237 p_offset = p_offset_start; \
238 for( i_x = i_pic_width / 16; i_x--; ) \
240 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
241 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
242 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
243 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
244 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
245 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
246 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
247 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
248 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
249 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
250 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
251 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
252 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
253 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
254 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
255 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
257 p_pic += i_pic_line_width; \
261 /* No scaling, conversion has been done directly in picture memory. \
262 * Increment of picture pointer to end of line is still needed */ \
263 p_pic += i_pic_width + i_pic_line_width; \
267 /*****************************************************************************
268 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
269 *****************************************************************************
270 * This macro scales a line using an offset array.
271 *****************************************************************************/
272 #define SCALE_WIDTH_DITHER( CHROMA ) \
273 if( b_horizontal_scaling ) \
275 /* Horizontal scaling, but we can't use a buffer due to dither */ \
276 p_offset = p_offset_start; \
278 for( i_x = i_pic_width / 16; i_x--; ) \
280 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
281 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
282 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
283 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
288 for( i_x = i_width / 16; i_x--; ) \
290 CONVERT_4YUV_PIXELS( CHROMA ) \
291 CONVERT_4YUV_PIXELS( CHROMA ) \
292 CONVERT_4YUV_PIXELS( CHROMA ) \
293 CONVERT_4YUV_PIXELS( CHROMA ) \
296 /* Increment of picture pointer to end of line is still needed */ \
297 p_pic += i_pic_line_width; \
298 i_real_y = (i_real_y + 1) & 0x3; \
300 /*****************************************************************************
301 * SCALE_HEIGHT: handle vertical scaling
302 *****************************************************************************
303 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
304 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
306 *****************************************************************************/
307 #define SCALE_HEIGHT( CHROMA, BPP ) \
308 /* If line is odd, rewind 4:2:0 U and V samples */ \
309 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
311 p_u -= i_chroma_width; \
312 p_v -= i_chroma_width; \
316 * Handle vertical scaling. The current line can be copied or next one \
319 switch( i_vertical_scaling ) \
321 case -1: /* vertical scaling factor is < 1 */ \
322 while( (i_scale_count -= i_pic_height) >= 0 ) \
324 /* Height reduction: skip next source line */ \
327 if( (CHROMA == 420) || (CHROMA == 422) ) \
331 p_u += i_chroma_width; \
332 p_v += i_chroma_width; \
335 else if( CHROMA == 444 ) \
341 i_scale_count += i_height; \
343 case 1: /* vertical scaling factor is > 1 */ \
344 while( (i_scale_count -= i_height) > 0 ) \
346 /* Height increment: copy previous picture line */ \
347 for( i_x = i_pic_width / 16; i_x--; ) \
349 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
350 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
351 if( BPP > 1 ) /* 2, 3, 4 Bpp */ \
353 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
354 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
356 if( BPP > 2 ) /* 3, 4 Bpp */ \
358 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
359 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
361 if( BPP > 3 ) /* 4 Bpp */ \
363 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
364 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
367 p_pic += i_pic_line_width; \
368 p_pic_start += i_pic_line_width; \
370 i_scale_count += i_pic_height; \
374 /*****************************************************************************
375 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
376 *****************************************************************************
377 * This macro handles vertical scaling for a picture. CHROMA may be 420, 422 or
378 * 444 for RGB conversion, or 400 for gray conversion.
379 *****************************************************************************/
380 #define SCALE_HEIGHT_DITHER( CHROMA ) \
382 /* If line is odd, rewind 4:2:0 U and V samples */ \
383 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
385 p_u -= i_chroma_width; \
386 p_v -= i_chroma_width; \
390 * Handle vertical scaling. The current line can be copied or next one \
394 switch( i_vertical_scaling ) \
396 case -1: /* vertical scaling factor is < 1 */ \
397 while( (i_scale_count -= i_pic_height) >= 0 ) \
399 /* Height reduction: skip next source line */ \
402 if( (CHROMA == 420) || (CHROMA == 422) ) \
406 p_u += i_chroma_width; \
407 p_v += i_chroma_width; \
410 else if( CHROMA == 444 ) \
416 i_scale_count += i_height; \
418 case 1: /* vertical scaling factor is > 1 */ \
419 while( (i_scale_count -= i_height) > 0 ) \
421 SCALE_WIDTH_DITHER( CHROMA ); \
423 p_u -= i_chroma_width; \
424 p_v -= i_chroma_width; \
425 p_pic += i_pic_line_width; \
427 i_scale_count += i_pic_height; \
431 /*****************************************************************************
432 * vout_InitYUV: allocate and initialize translations tables
433 *****************************************************************************
434 * This function will allocate memory to store translation tables, depending
435 * of the screen depth.
436 *****************************************************************************/
437 int vout_InitYUV( vout_thread_t *p_vout )
439 size_t tables_size; /* tables size, in bytes */
441 /* Computes tables size - 3 Bpp use 32 bits pixel entries in tables */
442 switch( p_vout->i_bytes_per_pixel )
445 tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE);
448 tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
453 tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
457 /* Allocate memory */
458 p_vout->yuv.p_base = malloc( tables_size );
459 if( p_vout->yuv.p_base == NULL )
461 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
465 /* Allocate memory for conversion buffer and offset array */
466 p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
467 if( p_vout->yuv.p_buffer == NULL )
469 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
470 free( p_vout->yuv.p_base );
473 p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );
474 if( p_vout->yuv.p_offset == NULL )
476 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
477 free( p_vout->yuv.p_base );
478 free( p_vout->yuv.p_buffer );
482 /* Initialize tables */
487 /*****************************************************************************
488 * vout_ResetTables: re-initialize translations tables
489 *****************************************************************************
490 * This function will initialize the tables allocated by vout_CreateTables and
491 * set functions pointers.
492 *****************************************************************************/
493 int vout_ResetYUV( vout_thread_t *p_vout )
495 vout_EndYUV( p_vout );
496 return( vout_InitYUV( p_vout ) );
499 /*****************************************************************************
500 * vout_EndYUV: destroy translations tables
501 *****************************************************************************
502 * Free memory allocated by vout_CreateTables.
503 *****************************************************************************/
504 void vout_EndYUV( vout_thread_t *p_vout )
506 free( p_vout->yuv.p_base );
507 free( p_vout->yuv.p_buffer );
508 free( p_vout->yuv.p_offset );
511 /* following functions are local */
513 /*****************************************************************************
514 * SetGammaTable: return intensity table transformed by gamma curve.
515 *****************************************************************************
516 * pi_table is a table of 256 entries from 0 to 255.
517 *****************************************************************************/
518 static void SetGammaTable( int *pi_table, double f_gamma )
520 int i_y; /* base intensity */
522 /* Use exp(gamma) instead of gamma */
523 f_gamma = exp( f_gamma );
525 /* Build gamma table */
526 for( i_y = 0; i_y < 256; i_y++ )
528 pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
532 /*****************************************************************************
533 * SetYUV: compute tables and set function pointers
534 + *****************************************************************************/
535 static void SetYUV( vout_thread_t *p_vout )
537 int pi_gamma[256]; /* gamma table */
538 int i_index; /* index in tables */
540 /* Build gamma table */
541 SetGammaTable( pi_gamma, p_vout->f_gamma );
544 * Set pointers and build YUV tables
546 if( p_vout->b_grayscale )
548 /* Grayscale: build gray table */
549 switch( p_vout->i_bytes_per_pixel )
553 u16 bright[256], transp[256];
555 p_vout->yuv.yuv.p_gray8 = (u8 *)p_vout->yuv.p_base + GRAY_MARGIN;
556 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
558 p_vout->yuv.yuv.p_gray8[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
559 p_vout->yuv.yuv.p_gray8[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
561 for( i_index = 0; i_index < 256; i_index++)
563 p_vout->yuv.yuv.p_gray8[ i_index ] = pi_gamma[ i_index ];
564 bright[ i_index ] = i_index << 8;
565 transp[ i_index ] = 0;
567 /* the colors have been allocated, we can set the palette */
568 p_vout->p_set_palette( p_vout, bright, bright, bright, transp );
569 p_vout->i_white_pixel = 0xff;
570 p_vout->i_black_pixel = 0x00;
571 p_vout->i_gray_pixel = 0x44;
572 p_vout->i_blue_pixel = 0x3b;
577 p_vout->yuv.yuv.p_gray16 = (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
578 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
580 p_vout->yuv.yuv.p_gray16[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
581 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
583 for( i_index = 0; i_index < 256; i_index++)
585 p_vout->yuv.yuv.p_gray16[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
590 p_vout->yuv.yuv.p_gray32 = (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
591 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
593 p_vout->yuv.yuv.p_gray32[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
594 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
596 for( i_index = 0; i_index < 256; i_index++)
598 p_vout->yuv.yuv.p_gray32[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
605 /* Color: build red, green and blue tables */
606 switch( p_vout->i_bytes_per_pixel )
612 #define SATURATE( x ) \
613 x = x + ( x >> 3 ) - 16; \
615 if( x > 255 ) x = 255;
621 u16 red[256], green[256], blue[256], transp[256];
622 unsigned char lookup[PALETTE_TABLE_SIZE];
624 p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
626 /* this loop calculates the intersection of an YUV box
627 * and the RGB cube. */
628 for ( y = 0; y <= 256; y += 16 )
630 for ( u = 0; u <= 256; u += 32 )
631 for ( v = 0; v <= 256; v += 32 )
633 uvr = (V_RED_COEF*(v-128)) >> SHIFT;
634 uvg = (U_GREEN_COEF*(u-128) + V_GREEN_COEF*(v-128)) >> SHIFT;
635 uvb = (U_BLUE_COEF*(u-128)) >> SHIFT;
640 if( r >= RGB_MIN && g >= RGB_MIN && b >= RGB_MIN
641 && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
643 /* this one should never happen unless someone fscked up my code */
644 if(j == 256) { intf_DbgMsg( "sorry, no colors left\n" ); exit( 1 ); }
646 /* saturate the colors */
658 p_vout->yuv.yuv.p_rgb8[i++] = j;
664 p_vout->yuv.yuv.p_rgb8[i++] = 0;
670 /* the colors have been allocated, we can set the palette */
671 /* there will eventually be a way to know which colors
672 * couldn't be allocated and try to find a replacement */
673 p_vout->p_set_palette( p_vout, red, green, blue, transp );
675 p_vout->i_white_pixel = 0xff;
676 p_vout->i_black_pixel = 0x00;
677 p_vout->i_gray_pixel = 0x44;
678 p_vout->i_blue_pixel = 0x3b;
681 /* this loop allocates colors that got outside
683 for ( y = 0; y <= 256; y += 16 )
685 for ( u = 0; u <= 256; u += 32 )
686 for ( v = 0; v <= 256; v += 32 )
689 int dist, mindist = 100000000;
691 if( lookup[i] || y==0)
698 for( u2 = 0; u2 <= 256; u2 += 32 )
699 for( v2 = 0; v2 <= 256; v2 += 32 )
701 j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
702 dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
704 /* find the nearest color */
707 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
712 /* find the nearest color */
713 if( dist + 128 < mindist )
715 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
716 mindist = dist + 128;
727 p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
728 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
730 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
731 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
733 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
735 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
736 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
738 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
740 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
741 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
743 for( i_index = 0; i_index < 256; i_index++ )
745 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
746 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
747 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
752 p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
753 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
755 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
756 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
758 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
760 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
761 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
763 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
765 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
766 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
768 for( i_index = 0; i_index < 256; i_index++ )
770 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
771 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
772 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
779 * Set functions pointers
781 if( p_vout->b_grayscale )
784 switch( p_vout->i_bytes_per_pixel )
787 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;
788 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;
789 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;
792 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
793 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
794 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
797 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
798 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
799 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
802 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
803 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
804 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
811 switch( p_vout->i_bytes_per_pixel )
814 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
815 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
816 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
819 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB16;
820 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB16;
821 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB16;
824 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB24;
825 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB24;
826 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB24;
829 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB32;
830 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB32;
831 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB32;
837 /*****************************************************************************
838 * SetOffset: build offset array for conversion functions
839 *****************************************************************************
840 * This function will build an offset array used in later conversion functions.
841 * It will also set horizontal and vertical scaling indicators.
842 *****************************************************************************/
843 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
844 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
846 int i_x; /* x position in destination */
847 int i_scale_count; /* modulo counter */
850 * Prepare horizontal offset array
852 if( i_pic_width - i_width > 0 )
854 /* Prepare scaling array for horizontal extension */
856 i_scale_count = i_pic_width;
857 for( i_x = i_width; i_x--; )
859 while( (i_scale_count -= i_width) > 0 )
864 i_scale_count += i_pic_width;
867 else if( i_pic_width - i_width < 0 )
869 /* Prepare scaling array for horizontal reduction */
871 i_scale_count = i_pic_width;
872 for( i_x = i_pic_width; i_x--; )
875 while( (i_scale_count -= i_pic_width) >= 0 )
880 i_scale_count += i_width;
885 /* No horizontal scaling: YUV conversion is done directly to picture */
890 * Set vertical scaling indicator
892 if( i_pic_height - i_height > 0 )
896 else if( i_pic_height - i_height < 0 )
906 /*****************************************************************************
907 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
908 *****************************************************************************/
909 static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
910 yuv_data_t *p_u, yuv_data_t *p_v, int i_width,
911 int i_height, int i_pic_width, int i_pic_height,
912 int i_pic_line_width, int i_matrix_coefficients )
914 boolean_t b_horizontal_scaling; /* horizontal scaling type */
915 int i_vertical_scaling; /* vertical scaling type */
916 int i_x, i_y; /* horizontal and vertical indexes */
917 int i_scale_count; /* scale modulo counter */
918 int i_chroma_width; /* chroma width, not used */
919 u8 * p_gray; /* base conversion table */
920 u8 * p_pic_start; /* beginning of the current line for copy */
921 u8 * p_buffer_start; /* conversion buffer start */
922 u8 * p_buffer; /* conversion buffer pointer */
923 int * p_offset_start; /* offset array start */
924 int * p_offset; /* offset array pointer */
927 * Initialize some values - i_pic_line_width will store the line skip
929 i_pic_line_width -= i_pic_width;
930 p_gray = p_vout->yuv.yuv.p_gray8;
931 p_buffer_start = p_vout->yuv.p_buffer;
932 p_offset_start = p_vout->yuv.p_offset;
933 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
934 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
939 i_scale_count = i_pic_height;
940 for( i_y = 0; i_y < i_height; i_y++ )
942 /* Mark beginnning of line for possible later line copy, and initialize
945 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
947 /* Do YUV conversion to buffer - YUV picture is always formed of 16
948 * pixels wide blocks */
949 for( i_x = i_width / 16; i_x--; )
951 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
952 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
953 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
954 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
955 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
956 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
957 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
958 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
961 /* Do horizontal and vertical scaling */
963 SCALE_HEIGHT(400, 1);
967 /*****************************************************************************
968 * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
969 *****************************************************************************/
970 static void ConvertY4Gray16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
971 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
972 int i_matrix_coefficients )
974 boolean_t b_horizontal_scaling; /* horizontal scaling type */
975 int i_vertical_scaling; /* vertical scaling type */
976 int i_x, i_y; /* horizontal and vertical indexes */
977 int i_scale_count; /* scale modulo counter */
978 int i_chroma_width; /* chroma width, not used */
979 u16 * p_gray; /* base conversion table */
980 u16 * p_pic_start; /* beginning of the current line for copy */
981 u16 * p_buffer_start; /* conversion buffer start */
982 u16 * p_buffer; /* conversion buffer pointer */
983 int * p_offset_start; /* offset array start */
984 int * p_offset; /* offset array pointer */
987 * Initialize some values - i_pic_line_width will store the line skip
989 i_pic_line_width -= i_pic_width;
990 p_gray = p_vout->yuv.yuv.p_gray16;
991 p_buffer_start = p_vout->yuv.p_buffer;
992 p_offset_start = p_vout->yuv.p_offset;
993 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
994 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
999 i_scale_count = i_pic_height;
1000 for( i_y = 0; i_y < i_height; i_y++ )
1002 /* Mark beginnning of line for possible later line copy, and initialize
1004 p_pic_start = p_pic;
1005 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1007 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1008 * pixels wide blocks */
1009 for( i_x = i_width / 16; i_x--; )
1011 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1012 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1013 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1014 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1015 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1016 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1017 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1018 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1021 /* Do horizontal and vertical scaling */
1023 SCALE_HEIGHT(400, 2);
1027 /*****************************************************************************
1028 * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 3 Bpp
1029 *****************************************************************************/
1030 static void ConvertY4Gray24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1031 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1032 int i_matrix_coefficients )
1037 /*****************************************************************************
1038 * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
1039 *****************************************************************************/
1040 static void ConvertY4Gray32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1041 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1042 int i_matrix_coefficients )
1044 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1045 int i_vertical_scaling; /* vertical scaling type */
1046 int i_x, i_y; /* horizontal and vertical indexes */
1047 int i_scale_count; /* scale modulo counter */
1048 int i_chroma_width; /* chroma width, not used */
1049 u32 * p_gray; /* base conversion table */
1050 u32 * p_pic_start; /* beginning of the current line for copy */
1051 u32 * p_buffer_start; /* conversion buffer start */
1052 u32 * p_buffer; /* conversion buffer pointer */
1053 int * p_offset_start; /* offset array start */
1054 int * p_offset; /* offset array pointer */
1057 * Initialize some values - i_pic_line_width will store the line skip
1059 i_pic_line_width -= i_pic_width;
1060 p_gray = p_vout->yuv.yuv.p_gray32;
1061 p_buffer_start = p_vout->yuv.p_buffer;
1062 p_offset_start = p_vout->yuv.p_offset;
1063 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1064 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1067 * Perform conversion
1069 i_scale_count = i_pic_height;
1070 for( i_y = 0; i_y < i_height; i_y++ )
1072 /* Mark beginnning of line for possible later line copy, and initialize
1074 p_pic_start = p_pic;
1075 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1077 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1078 * pixels wide blocks */
1079 for( i_x = i_width / 16; i_x--; )
1081 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1082 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1083 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1084 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1085 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1086 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1087 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1088 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1091 /* Do horizontal and vertical scaling */
1093 SCALE_HEIGHT(400, 4);
1097 /*****************************************************************************
1098 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
1099 *****************************************************************************/
1100 static void ConvertYUV420RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1101 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1102 int i_matrix_coefficients )
1104 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1105 int i_vertical_scaling; /* vertical scaling type */
1106 int i_x, i_y; /* horizontal and vertical indexes */
1107 int i_scale_count; /* scale modulo counter */
1108 int b_jump_uv; /* should we jump u and v ? */
1109 int i_real_y; /* y % 4 */
1110 u8 * p_lookup; /* lookup table */
1111 int i_chroma_width; /* chroma width */
1112 int * p_offset_start; /* offset array start */
1113 int * p_offset; /* offset array pointer */
1115 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
1116 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
1117 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
1118 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
1119 int dither20[4] = { 0x00, 0x10, 0x04, 0x14 };
1120 int dither21[4] = { 0x18, 0x08, 0x1c, 0x0c };
1121 int dither22[4] = { 0x06, 0x16, 0x02, 0x12 };
1122 int dither23[4] = { 0x1e, 0x0e, 0x1a, 0x0a };
1124 /* other matrices that can be interesting, either for debugging or for effects */
1125 //int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
1126 //int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
1127 //int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
1128 //int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
1129 //int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
1130 //int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
1132 * Initialize some values - i_pic_line_width will store the line skip
1134 i_pic_line_width -= i_pic_width;
1135 i_chroma_width = i_width / 2;
1136 p_offset_start = p_vout->yuv.p_offset;
1137 p_lookup = p_vout->yuv.p_base;
1138 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1139 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1142 * Perform conversion
1144 i_scale_count = i_pic_height;
1146 for( i_y = 0; i_y < i_height; i_y++ )
1148 /* Do horizontal and vertical scaling */
1149 SCALE_WIDTH_DITHER( 420 );
1150 SCALE_HEIGHT_DITHER( 420 );
1154 /*****************************************************************************
1155 * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1156 *****************************************************************************/
1157 static void ConvertYUV422RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1158 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1159 int i_matrix_coefficients )
1161 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1162 int i_vertical_scaling; /* vertical scaling type */
1163 int i_x, i_y; /* horizontal and vertical indexes */
1164 int i_scale_count; /* scale modulo counter */
1165 int i_uval, i_vval; /* U and V samples */
1166 int i_red, i_green, i_blue; /* U and V modified samples */
1167 int i_chroma_width; /* chroma width */
1168 u8 * p_yuv; /* base conversion table */
1169 u8 * p_ybase; /* Y dependant conversion table */
1170 u8 * p_pic_start; /* beginning of the current line for copy */
1171 u8 * p_buffer_start; /* conversion buffer start */
1172 u8 * p_buffer; /* conversion buffer pointer */
1173 int * p_offset_start; /* offset array start */
1174 int * p_offset; /* offset array pointer */
1177 * Initialize some values - i_pic_line_width will store the line skip
1179 i_pic_line_width -= i_pic_width;
1180 i_chroma_width = i_width / 2;
1181 p_yuv = p_vout->yuv.yuv.p_rgb8;
1182 p_buffer_start = p_vout->yuv.p_buffer;
1183 p_offset_start = p_vout->yuv.p_offset;
1184 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1185 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1188 * Perform conversion
1190 i_scale_count = i_pic_height;
1191 for( i_y = 0; i_y < i_height; i_y++ )
1193 /* Mark beginnning of line for possible later line copy, and initialize
1195 p_pic_start = p_pic;
1196 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1198 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1199 * pixels wide blocks */
1200 for( i_x = i_width / 16; i_x--; )
1202 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1203 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1204 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1205 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1206 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1207 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1208 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1209 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1212 /* Do horizontal and vertical scaling */
1214 SCALE_HEIGHT(422, 1);
1218 /*****************************************************************************
1219 * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1220 *****************************************************************************/
1221 static void ConvertYUV444RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1222 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1223 int i_matrix_coefficients )
1225 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1226 int i_vertical_scaling; /* vertical scaling type */
1227 int i_x, i_y; /* horizontal and vertical indexes */
1228 int i_scale_count; /* scale modulo counter */
1229 int i_uval, i_vval; /* U and V samples */
1230 int i_red, i_green, i_blue; /* U and V modified samples */
1231 int i_chroma_width; /* chroma width, not used */
1232 u8 * p_yuv; /* base conversion table */
1233 u8 * p_ybase; /* Y dependant conversion table */
1234 u8 * p_pic_start; /* beginning of the current line for copy */
1235 u8 * p_buffer_start; /* conversion buffer start */
1236 u8 * p_buffer; /* conversion buffer pointer */
1237 int * p_offset_start; /* offset array start */
1238 int * p_offset; /* offset array pointer */
1241 * Initialize some values - i_pic_line_width will store the line skip
1243 i_pic_line_width -= i_pic_width;
1244 p_yuv = p_vout->yuv.yuv.p_rgb8;
1245 p_buffer_start = p_vout->yuv.p_buffer;
1246 p_offset_start = p_vout->yuv.p_offset;
1247 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1248 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1251 * Perform conversion
1253 i_scale_count = i_pic_height;
1254 for( i_y = 0; i_y < i_height; i_y++ )
1256 /* Mark beginnning of line for possible later line copy, and initialize
1258 p_pic_start = p_pic;
1259 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1261 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1262 * pixels wide blocks */
1263 for( i_x = i_width / 16; i_x--; )
1265 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1266 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1267 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1268 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1269 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1270 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1271 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1272 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1275 /* Do horizontal and vertical scaling */
1277 SCALE_HEIGHT(444, 1);
1281 /*****************************************************************************
1282 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1283 *****************************************************************************/
1284 static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1285 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1286 int i_matrix_coefficients )
1289 // int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
1291 i_chroma_width = i_width / 2;
1292 i_chroma_skip = i_skip / 2;
1293 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1294 (i_width + i_skip) * sizeof( yuv_data_t ),
1295 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1296 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1297 p_vout->i_screen_depth == 15 );
1299 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1300 int i_vertical_scaling; /* vertical scaling type */
1301 int i_x, i_y; /* horizontal and vertical indexes */
1302 int i_scale_count; /* scale modulo counter */
1303 int i_uval, i_vval; /* U and V samples */
1304 int i_red, i_green, i_blue; /* U and V modified samples */
1305 int i_chroma_width; /* chroma width */
1306 u16 * p_yuv; /* base conversion table */
1307 u16 * p_ybase; /* Y dependant conversion table */
1308 u16 * p_pic_start; /* beginning of the current line for copy */
1309 u16 * p_buffer_start; /* conversion buffer start */
1310 u16 * p_buffer; /* conversion buffer pointer */
1311 int * p_offset_start; /* offset array start */
1312 int * p_offset; /* offset array pointer */
1315 * Initialize some values - i_pic_line_width will store the line skip
1317 i_pic_line_width -= i_pic_width;
1318 i_chroma_width = i_width / 2;
1319 p_yuv = p_vout->yuv.yuv.p_rgb16;
1320 p_buffer_start = p_vout->yuv.p_buffer;
1321 p_offset_start = p_vout->yuv.p_offset;
1322 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1323 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1326 * Perform conversion
1328 i_scale_count = i_pic_height;
1329 for( i_y = 0; i_y < i_height; i_y++ )
1331 /* Mark beginnning of line for possible later line copy, and initialize
1333 p_pic_start = p_pic;
1334 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1336 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1337 * pixels wide blocks */
1338 for( i_x = i_width / 16; i_x--; )
1340 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1341 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1342 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1343 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1344 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1345 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1346 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1347 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1350 /* Do horizontal and vertical scaling */
1352 SCALE_HEIGHT(420, 2);
1356 /*****************************************************************************
1357 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1358 *****************************************************************************/
1359 static void ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1360 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1361 int i_matrix_coefficients )
1363 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1364 int i_vertical_scaling; /* vertical scaling type */
1365 int i_x, i_y; /* horizontal and vertical indexes */
1366 int i_scale_count; /* scale modulo counter */
1367 int i_uval, i_vval; /* U and V samples */
1368 int i_red, i_green, i_blue; /* U and V modified samples */
1369 int i_chroma_width; /* chroma width */
1370 u16 * p_yuv; /* base conversion table */
1371 u16 * p_ybase; /* Y dependant conversion table */
1372 u16 * p_pic_start; /* beginning of the current line for copy */
1373 u16 * p_buffer_start; /* conversion buffer start */
1374 u16 * p_buffer; /* conversion buffer pointer */
1375 int * p_offset_start; /* offset array start */
1376 int * p_offset; /* offset array pointer */
1379 * Initialize some values - i_pic_line_width will store the line skip
1381 i_pic_line_width -= i_pic_width;
1382 i_chroma_width = i_width / 2;
1383 p_yuv = p_vout->yuv.yuv.p_rgb16;
1384 p_buffer_start = p_vout->yuv.p_buffer;
1385 p_offset_start = p_vout->yuv.p_offset;
1386 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1387 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1390 * Perform conversion
1392 i_scale_count = i_pic_height;
1393 for( i_y = 0; i_y < i_height; i_y++ )
1395 /* Mark beginnning of line for possible later line copy, and initialize
1397 p_pic_start = p_pic;
1398 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1400 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1401 * pixels wide blocks */
1402 for( i_x = i_width / 16; i_x--; )
1404 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1405 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1406 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1407 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1408 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1409 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1410 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1411 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1414 /* Do horizontal and vertical scaling */
1416 SCALE_HEIGHT(422, 2);
1420 /*****************************************************************************
1421 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1422 *****************************************************************************/
1423 static void ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1424 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1425 int i_matrix_coefficients )
1427 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1428 int i_vertical_scaling; /* vertical scaling type */
1429 int i_x, i_y; /* horizontal and vertical indexes */
1430 int i_scale_count; /* scale modulo counter */
1431 int i_uval, i_vval; /* U and V samples */
1432 int i_red, i_green, i_blue; /* U and V modified samples */
1433 int i_chroma_width; /* chroma width, not used */
1434 u16 * p_yuv; /* base conversion table */
1435 u16 * p_ybase; /* Y dependant conversion table */
1436 u16 * p_pic_start; /* beginning of the current line for copy */
1437 u16 * p_buffer_start; /* conversion buffer start */
1438 u16 * p_buffer; /* conversion buffer pointer */
1439 int * p_offset_start; /* offset array start */
1440 int * p_offset; /* offset array pointer */
1443 * Initialize some values - i_pic_line_width will store the line skip
1445 i_pic_line_width -= i_pic_width;
1446 p_yuv = p_vout->yuv.yuv.p_rgb16;
1447 p_buffer_start = p_vout->yuv.p_buffer;
1448 p_offset_start = p_vout->yuv.p_offset;
1449 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1450 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1453 * Perform conversion
1455 i_scale_count = i_pic_height;
1456 for( i_y = 0; i_y < i_height; i_y++ )
1458 /* Mark beginnning of line for possible later line copy, and initialize
1460 p_pic_start = p_pic;
1461 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1463 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1464 * pixels wide blocks */
1465 for( i_x = i_width / 16; i_x--; )
1467 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1468 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1469 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1470 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1471 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1472 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1473 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1474 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1477 /* Do horizontal and vertical scaling */
1479 SCALE_HEIGHT(444, 2);
1483 /*****************************************************************************
1484 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1485 *****************************************************************************/
1486 static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1487 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1488 int i_matrix_coefficients )
1493 /*****************************************************************************
1494 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1495 *****************************************************************************/
1496 static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1497 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1498 int i_matrix_coefficients )
1503 /*****************************************************************************
1504 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1505 *****************************************************************************/
1506 static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1507 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1508 int i_matrix_coefficients )
1513 /*****************************************************************************
1514 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1515 *****************************************************************************/
1516 static void ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1517 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1518 int i_matrix_coefficients )
1520 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1521 int i_vertical_scaling; /* vertical scaling type */
1522 int i_x, i_y; /* horizontal and vertical indexes */
1523 int i_scale_count; /* scale modulo counter */
1524 int i_uval, i_vval; /* U and V samples */
1525 int i_red, i_green, i_blue; /* U and V modified samples */
1526 int i_chroma_width; /* chroma width */
1527 u32 * p_yuv; /* base conversion table */
1528 u32 * p_ybase; /* Y dependant conversion table */
1529 u32 * p_pic_start; /* beginning of the current line for copy */
1530 u32 * p_buffer_start; /* conversion buffer start */
1531 u32 * p_buffer; /* conversion buffer pointer */
1532 int * p_offset_start; /* offset array start */
1533 int * p_offset; /* offset array pointer */
1536 * Initialize some values - i_pic_line_width will store the line skip
1538 i_pic_line_width -= i_pic_width;
1539 i_chroma_width = i_width / 2;
1540 p_yuv = p_vout->yuv.yuv.p_rgb32;
1541 p_buffer_start = p_vout->yuv.p_buffer;
1542 p_offset_start = p_vout->yuv.p_offset;
1543 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1544 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1547 * Perform conversion
1549 i_scale_count = i_pic_height;
1550 for( i_y = 0; i_y < i_height; i_y++ )
1552 /* Mark beginnning of line for possible later line copy, and initialize
1554 p_pic_start = p_pic;
1555 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1557 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1558 * pixels wide blocks */
1559 for( i_x = i_width / 16; i_x--; )
1561 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1562 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1563 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1564 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1565 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1566 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1567 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1568 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1571 /* Do horizontal and vertical scaling */
1573 SCALE_HEIGHT(420, 4);
1577 /*****************************************************************************
1578 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1579 *****************************************************************************/
1580 static void ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1581 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1582 int i_matrix_coefficients )
1584 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1585 int i_vertical_scaling; /* vertical scaling type */
1586 int i_x, i_y; /* horizontal and vertical indexes */
1587 int i_scale_count; /* scale modulo counter */
1588 int i_uval, i_vval; /* U and V samples */
1589 int i_red, i_green, i_blue; /* U and V modified samples */
1590 int i_chroma_width; /* chroma width */
1591 u32 * p_yuv; /* base conversion table */
1592 u32 * p_ybase; /* Y dependant conversion table */
1593 u32 * p_pic_start; /* beginning of the current line for copy */
1594 u32 * p_buffer_start; /* conversion buffer start */
1595 u32 * p_buffer; /* conversion buffer pointer */
1596 int * p_offset_start; /* offset array start */
1597 int * p_offset; /* offset array pointer */
1600 * Initialize some values - i_pic_line_width will store the line skip
1602 i_pic_line_width -= i_pic_width;
1603 i_chroma_width = i_width / 2;
1604 p_yuv = p_vout->yuv.yuv.p_rgb32;
1605 p_buffer_start = p_vout->yuv.p_buffer;
1606 p_offset_start = p_vout->yuv.p_offset;
1607 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1608 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1611 * Perform conversion
1613 i_scale_count = i_pic_height;
1614 for( i_y = 0; i_y < i_height; i_y++ )
1616 /* Mark beginnning of line for possible later line copy, and initialize
1618 p_pic_start = p_pic;
1619 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1621 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1622 * pixels wide blocks */
1623 for( i_x = i_width / 16; i_x--; )
1625 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1626 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1627 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1628 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1629 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1630 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1631 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1632 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1635 /* Do horizontal and vertical scaling */
1637 SCALE_HEIGHT(422, 4);
1641 /*****************************************************************************
1642 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1643 *****************************************************************************/
1644 static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
1645 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1646 int i_matrix_coefficients )
1648 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1649 int i_vertical_scaling; /* vertical scaling type */
1650 int i_x, i_y; /* horizontal and vertical indexes */
1651 int i_scale_count; /* scale modulo counter */
1652 int i_uval, i_vval; /* U and V samples */
1653 int i_red, i_green, i_blue; /* U and V modified samples */
1654 int i_chroma_width; /* chroma width, not used */
1655 u32 * p_yuv; /* base conversion table */
1656 u32 * p_ybase; /* Y dependant conversion table */
1657 u32 * p_pic_start; /* beginning of the current line for copy */
1658 u32 * p_buffer_start; /* conversion buffer start */
1659 u32 * p_buffer; /* conversion buffer pointer */
1660 int * p_offset_start; /* offset array start */
1661 int * p_offset; /* offset array pointer */
1664 * Initialize some values - i_pic_line_width will store the line skip
1666 i_pic_line_width -= i_pic_width;
1667 p_yuv = p_vout->yuv.yuv.p_rgb32;
1668 p_buffer_start = p_vout->yuv.p_buffer;
1669 p_offset_start = p_vout->yuv.p_offset;
1670 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1671 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1674 * Perform conversion
1676 i_scale_count = i_pic_height;
1677 for( i_y = 0; i_y < i_height; i_y++ )
1679 /* Mark beginnning of line for possible later line copy, and initialize
1681 p_pic_start = p_pic;
1682 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1684 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1685 * pixels wide blocks */
1686 for( i_x = i_width / 16; i_x--; )
1688 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1689 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1690 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1691 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1692 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1693 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1694 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1695 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1698 /* Do horizontal and vertical scaling */
1700 SCALE_HEIGHT(444, 4);
1704 //-------------------- walken code follows ------------------------------------
1707 * YUV to RGB routines.
1709 * these routines calculate r, g and b values from each pixel's y, u and v.
1710 * these r, g an b values are then passed thru a table lookup to take the
1711 * gamma curve into account and find the corresponding pixel value.
1713 * the table must store more than 3*256 values because of the possibility
1714 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1715 * values are in the following intervals :
1716 * -176 to 255+176 for red
1717 * -133 to 255+133 for green
1718 * -222 to 255+222 for blue
1720 * If the input y,u,v values are right, the r,g,b results are not expected
1721 * to move out of the 0 to 255 interval but who knows what will happen in
1724 * the red, green and blue conversion tables are stored in a single 1935-entry
1725 * array. The respective positions of each component in the array have been
1726 * calculated to minimize the cache interactions of the 3 tables.
1731 static void yuvToRgb24 (unsigned char * Y,
1732 unsigned char * U, unsigned char * V,
1733 char * dest, int table[1935], int width)
1748 uvRed = (V_RED_COEF*v) >> SHIFT;
1749 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1750 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1752 tableY = table + *(Y++);
1753 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1754 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1756 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1758 *(dest++) = tmp24 >> 8;
1759 *(dest++) = tmp24 >> 16;
1761 tableY = table + *(Y++);
1762 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1763 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1765 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1767 *(dest++) = tmp24 >> 8;
1768 *(dest++) = tmp24 >> 16;
1772 uvRed = (V_RED_COEF*v) >> SHIFT;
1773 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1774 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1776 tableY = table + *(Y++);
1777 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1778 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1780 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1782 *(dest++) = tmp24 >> 8;
1783 *(dest++) = tmp24 >> 16;
1785 tableY = table + *(Y++);
1786 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1787 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1789 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1791 *(dest++) = tmp24 >> 8;
1792 *(dest++) = tmp24 >> 16;
1796 uvRed = (V_RED_COEF*v) >> SHIFT;
1797 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1798 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1800 tableY = table + *(Y++);
1801 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1802 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1804 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1806 *(dest++) = tmp24 >> 8;
1807 *(dest++) = tmp24 >> 16;
1809 tableY = table + *(Y++);
1810 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1811 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1813 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1815 *(dest++) = tmp24 >> 8;
1816 *(dest++) = tmp24 >> 16;
1820 uvRed = (V_RED_COEF*v) >> SHIFT;
1821 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1822 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1824 tableY = table + *(Y++);
1825 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1826 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1828 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1830 *(dest++) = tmp24 >> 8;
1831 *(dest++) = tmp24 >> 16;
1833 tableY = table + *(Y++);
1834 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1835 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1837 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1839 *(dest++) = tmp24 >> 8;
1840 *(dest++) = tmp24 >> 16;
1843 i = (width & 7) >> 1;
1847 uvRed = (V_RED_COEF*v) >> SHIFT;
1848 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1849 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1851 tableY = table + *(Y++);
1852 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1853 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1855 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1857 *(dest++) = tmp24 >> 8;
1858 *(dest++) = tmp24 >> 16;
1860 tableY = table + *(Y++);
1861 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1862 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1864 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1866 *(dest++) = tmp24 >> 8;
1867 *(dest++) = tmp24 >> 16;
1873 uvRed = (V_RED_COEF*v) >> SHIFT;
1874 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1875 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1877 tableY = table + *(Y++);
1878 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1879 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1881 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1883 *(dest++) = tmp24 >> 8;
1884 *(dest++) = tmp24 >> 16;