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 /* Margins and offsets in conversion tables - Margins are used in case a RGB
32 * RGB conversion would give a value outside the 0-255 range. Offsets have been
33 * calculated to avoid using the same cache line for 2 tables. conversion tables
34 * are 2*MARGIN + 256 long and stores pixels.*/
35 #define RED_MARGIN 178
36 #define GREEN_MARGIN 135
37 #define BLUE_MARGIN 224
38 #define RED_OFFSET 1501 /* 1323 to 1935 */
39 #define GREEN_OFFSET 135 /* 0 to 526 */
40 #define BLUE_OFFSET 818 /* 594 to 1298 */
41 #define RGB_TABLE_SIZE 1935 /* total table size */
43 #define GRAY_MARGIN 384
44 #define GRAY_TABLE_SIZE 1024 /* total table size */
46 #define PALETTE_TABLE_SIZE 2176 /* YUV -> 8bpp palette lookup table */
48 /* macros used for YUV pixel conversions */
50 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
51 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
52 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
53 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
55 /*****************************************************************************
57 *****************************************************************************/
58 static void SetGammaTable ( int *pi_table, double f_gamma );
59 static void SetYUV ( vout_thread_t *p_vout );
60 static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height,
61 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
63 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,
64 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
65 int i_matrix_coefficients );
66 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,
67 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
68 int i_matrix_coefficients );
69 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,
70 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
71 int i_matrix_coefficients );
72 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,
73 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
74 int i_matrix_coefficients );
75 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,
76 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
77 int i_matrix_coefficients );
78 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,
79 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
80 int i_matrix_coefficients );
81 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,
82 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
83 int i_matrix_coefficients );
84 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,
85 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
86 int i_matrix_coefficients );
87 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,
88 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
89 int i_matrix_coefficients );
90 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,
91 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
92 int i_matrix_coefficients );
93 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,
94 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
95 int i_matrix_coefficients );
96 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,
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 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,
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 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,
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 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,
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 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,
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 );
112 /*****************************************************************************
113 * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel conversion blocks
114 *****************************************************************************
115 * These conversion routines are used by YUV conversion functions.
116 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
117 * which is also modified.
118 *****************************************************************************/
119 #define CONVERT_Y_PIXEL( BPP ) \
120 /* Only Y sample is present */ \
121 p_ybase = p_yuv + *p_y++; \
122 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
123 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
124 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
126 #define CONVERT_YUV_PIXEL( BPP ) \
127 /* Y, U and V samples are present */ \
130 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
131 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
132 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
133 CONVERT_Y_PIXEL( BPP ) \
135 /*****************************************************************************
136 * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp
137 *****************************************************************************
138 * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
139 *****************************************************************************/
140 #define CONVERT_4YUV_PIXELS( CHROMA ) \
141 *p_pic++ = p_lookup[ \
142 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
143 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
144 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
145 *p_pic++ = p_lookup[ \
146 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
147 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
148 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
149 *p_pic++ = p_lookup[ \
150 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
151 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
152 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
153 *p_pic++ = p_lookup[ \
154 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
155 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
156 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
158 #define CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
159 *p_pic++ = p_lookup[ \
160 (((*p_y + dither10[i_real_y]) >> 4) << 7) \
161 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
162 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
163 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
165 p_u += *p_offset & b_jump_uv; \
166 p_v += *p_offset++ & b_jump_uv; \
167 *p_pic++ = p_lookup[ \
168 (((*p_y + dither11[i_real_y]) >> 4) << 7) \
169 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
170 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
171 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
173 p_u += *p_offset & b_jump_uv; \
174 p_v += *p_offset++ & b_jump_uv; \
175 *p_pic++ = p_lookup[ \
176 (((*p_y + dither12[i_real_y]) >> 4) << 7) \
177 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
178 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
179 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
181 p_u += *p_offset & b_jump_uv; \
182 p_v += *p_offset++ & b_jump_uv; \
183 *p_pic++ = p_lookup[ \
184 (((*p_y + dither13[i_real_y]) >> 4) << 7) \
185 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
186 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
187 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
189 p_u += *p_offset & b_jump_uv; \
190 p_v += *p_offset++ & b_jump_uv; \
192 /*****************************************************************************
193 * SCALE_WIDTH: scale a line horizontally
194 *****************************************************************************
195 * This macro scales a line using rendering buffer and offset array. It works
196 * for 1, 2 and 4 Bpp.
197 *****************************************************************************/
198 #define SCALE_WIDTH \
199 if( b_horizontal_scaling ) \
201 /* Horizontal scaling, conversion has been done to buffer. \
202 * Rewind buffer and offset, then copy and scale line */ \
203 p_buffer = p_buffer_start; \
204 p_offset = p_offset_start; \
205 for( i_x = i_pic_width / 16; i_x--; ) \
207 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
208 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
209 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
210 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
211 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
212 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
213 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
214 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
215 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
216 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
217 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
218 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
219 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
220 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
221 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
222 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
224 p_pic += i_pic_line_width; \
228 /* No scaling, conversion has been done directly in picture memory. \
229 * Increment of picture pointer to end of line is still needed */ \
230 p_pic += i_pic_width + i_pic_line_width; \
234 /*****************************************************************************
235 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
236 *****************************************************************************
237 * This macro scales a line using an offset array.
238 *****************************************************************************/
239 #define SCALE_WIDTH_DITHER( CHROMA ) \
240 if( b_horizontal_scaling ) \
242 /* Horizontal scaling, but we can't use a buffer due to dither */ \
243 p_offset = p_offset_start; \
245 for( i_x = i_pic_width / 16; i_x--; ) \
247 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
248 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
249 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
250 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
255 for( i_x = i_width / 16; i_x--; ) \
257 CONVERT_4YUV_PIXELS( CHROMA ) \
258 CONVERT_4YUV_PIXELS( CHROMA ) \
259 CONVERT_4YUV_PIXELS( CHROMA ) \
260 CONVERT_4YUV_PIXELS( CHROMA ) \
263 /* Increment of picture pointer to end of line is still needed */ \
264 p_pic += i_pic_line_width; \
265 i_real_y = (i_real_y + 1) & 0x3; \
267 /*****************************************************************************
268 * SCALE_HEIGHT: handle vertical scaling
269 *****************************************************************************
270 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
271 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
273 *****************************************************************************/
274 #define SCALE_HEIGHT( CHROMA, BPP ) \
275 /* If line is odd, rewind 4:2:0 U and V samples */ \
276 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
278 p_u -= i_chroma_width; \
279 p_v -= i_chroma_width; \
283 * Handle vertical scaling. The current line can be copied or next one \
286 switch( i_vertical_scaling ) \
288 case -1: /* vertical scaling factor is < 1 */ \
289 while( (i_scale_count -= i_pic_height) >= 0 ) \
291 /* Height reduction: skip next source line */ \
294 if( (CHROMA == 420) || (CHROMA == 422) ) \
298 p_u += i_chroma_width; \
299 p_v += i_chroma_width; \
302 else if( CHROMA == 444 ) \
308 i_scale_count += i_height; \
310 case 1: /* vertical scaling factor is > 1 */ \
311 while( (i_scale_count -= i_height) > 0 ) \
313 /* Height increment: copy previous picture line */ \
314 for( i_x = i_pic_width / 16; i_x--; ) \
316 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
317 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
318 if( BPP > 1 ) /* 2, 3, 4 Bpp */ \
320 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
321 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
323 if( BPP > 2 ) /* 3, 4 Bpp */ \
325 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
326 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
328 if( BPP > 3 ) /* 4 Bpp */ \
330 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
331 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
334 p_pic += i_pic_line_width; \
335 p_pic_start += i_pic_line_width; \
337 i_scale_count += i_pic_height; \
341 /*****************************************************************************
342 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
343 *****************************************************************************
344 * This macro handles vertical scaling for a picture. CHROMA may be 420, 422 or
345 * 444 for RGB conversion, or 400 for gray conversion.
346 *****************************************************************************/
347 #define SCALE_HEIGHT_DITHER( CHROMA ) \
349 /* If line is odd, rewind 4:2:0 U and V samples */ \
350 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
352 p_u -= i_chroma_width; \
353 p_v -= i_chroma_width; \
357 * Handle vertical scaling. The current line can be copied or next one \
361 switch( i_vertical_scaling ) \
363 case -1: /* vertical scaling factor is < 1 */ \
364 while( (i_scale_count -= i_pic_height) >= 0 ) \
366 /* Height reduction: skip next source line */ \
369 if( (CHROMA == 420) || (CHROMA == 422) ) \
373 p_u += i_chroma_width; \
374 p_v += i_chroma_width; \
377 else if( CHROMA == 444 ) \
383 i_scale_count += i_height; \
385 case 1: /* vertical scaling factor is > 1 */ \
386 while( (i_scale_count -= i_height) > 0 ) \
388 SCALE_WIDTH_DITHER( CHROMA ); \
390 p_u -= i_chroma_width; \
391 p_v -= i_chroma_width; \
392 p_pic += i_pic_line_width; \
394 i_scale_count += i_pic_height; \
398 /*****************************************************************************
399 * vout_InitYUV: allocate and initialize translations tables
400 *****************************************************************************
401 * This function will allocate memory to store translation tables, depending
402 * of the screen depth.
403 *****************************************************************************/
404 int vout_InitYUV( vout_thread_t *p_vout )
406 size_t tables_size; /* tables size, in bytes */
408 /* Computes tables size - 3 Bpp use 32 bits pixel entries in tables */
409 switch( p_vout->i_bytes_per_pixel )
412 tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE);
415 tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
420 tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
424 /* Allocate memory */
425 p_vout->yuv.p_base = malloc( tables_size );
426 if( p_vout->yuv.p_base == NULL )
428 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
432 /* Allocate memory for conversion buffer and offset array */
433 p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
434 if( p_vout->yuv.p_buffer == NULL )
436 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
437 free( p_vout->yuv.p_base );
440 p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );
441 if( p_vout->yuv.p_offset == NULL )
443 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
444 free( p_vout->yuv.p_base );
445 free( p_vout->yuv.p_buffer );
449 /* Initialize tables */
454 /*****************************************************************************
455 * vout_ResetTables: re-initialize translations tables
456 *****************************************************************************
457 * This function will initialize the tables allocated by vout_CreateTables and
458 * set functions pointers.
459 *****************************************************************************/
460 int vout_ResetYUV( vout_thread_t *p_vout )
462 vout_EndYUV( p_vout );
463 return( vout_InitYUV( p_vout ) );
466 /*****************************************************************************
467 * vout_EndYUV: destroy translations tables
468 *****************************************************************************
469 * Free memory allocated by vout_CreateTables.
470 *****************************************************************************/
471 void vout_EndYUV( vout_thread_t *p_vout )
473 free( p_vout->yuv.p_base );
474 free( p_vout->yuv.p_buffer );
475 free( p_vout->yuv.p_offset );
478 /* following functions are local */
480 /*****************************************************************************
481 * SetGammaTable: return intensity table transformed by gamma curve.
482 *****************************************************************************
483 * pi_table is a table of 256 entries from 0 to 255.
484 *****************************************************************************/
485 static void SetGammaTable( int *pi_table, double f_gamma )
487 int i_y; /* base intensity */
489 /* Use exp(gamma) instead of gamma */
490 f_gamma = exp( f_gamma );
492 /* Build gamma table */
493 for( i_y = 0; i_y < 256; i_y++ )
495 pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
499 /*****************************************************************************
500 * SetYUV: compute tables and set function pointers
501 + *****************************************************************************/
502 static void SetYUV( vout_thread_t *p_vout )
504 int pi_gamma[256]; /* gamma table */
505 int i_index; /* index in tables */
507 /* Build gamma table */
508 SetGammaTable( pi_gamma, p_vout->f_gamma );
511 * Set pointers and build YUV tables
513 if( p_vout->b_grayscale )
515 /* Grayscale: build gray table */
516 switch( p_vout->i_bytes_per_pixel )
520 u16 bright[256], transp[256];
522 p_vout->yuv.yuv.p_gray8 = (u8 *)p_vout->yuv.p_base + GRAY_MARGIN;
523 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
525 p_vout->yuv.yuv.p_gray8[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
526 p_vout->yuv.yuv.p_gray8[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
528 for( i_index = 0; i_index < 256; i_index++)
530 p_vout->yuv.yuv.p_gray8[ i_index ] = pi_gamma[ i_index ];
531 bright[ i_index ] = i_index << 8;
532 transp[ i_index ] = 0;
534 /* the colors have been allocated, we can set the palette */
535 p_vout->p_set_palette( p_vout, bright, bright, bright, transp );
536 p_vout->i_white_pixel = 0xff;
537 p_vout->i_black_pixel = 0x00;
538 p_vout->i_gray_pixel = 0x44;
539 p_vout->i_blue_pixel = 0x3b;
544 p_vout->yuv.yuv.p_gray16 = (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
545 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
547 p_vout->yuv.yuv.p_gray16[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
548 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
550 for( i_index = 0; i_index < 256; i_index++)
552 p_vout->yuv.yuv.p_gray16[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
557 p_vout->yuv.yuv.p_gray32 = (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
558 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
560 p_vout->yuv.yuv.p_gray32[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
561 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
563 for( i_index = 0; i_index < 256; i_index++)
565 p_vout->yuv.yuv.p_gray32[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
572 /* Color: build red, green and blue tables */
573 switch( p_vout->i_bytes_per_pixel )
579 #define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 )
585 u16 red[256], green[256], blue[256], transp[256];
586 unsigned char lookup[PALETTE_TABLE_SIZE];
588 p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
590 /* this loop calculates the intersection of an YUV box
591 * and the RGB cube. */
592 for ( y = 0; y <= 256; y += 16 )
594 for ( u = 0; u <= 256; u += 32 )
595 for ( v = 0; v <= 256; v += 32 )
597 uvr = (V_RED_COEF*(v-128)) >> SHIFT;
598 uvg = (U_GREEN_COEF*(u-128) + V_GREEN_COEF*(v-128)) >> SHIFT;
599 uvb = (U_BLUE_COEF*(u-128)) >> SHIFT;
604 if( r >= RGB_MIN && g >= RGB_MIN && b >= RGB_MIN
605 && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
607 /* this one should never happen unless someone fscked up my code */
608 if(j == 256) { intf_ErrMsg( "vout error: no colors left to build palette\n" ); break; }
610 /* clip the colors */
612 green[j] = CLIP( g );
618 p_vout->yuv.yuv.p_rgb8[i++] = j;
624 p_vout->yuv.yuv.p_rgb8[i++] = 0;
630 /* the colors have been allocated, we can set the palette */
631 /* there will eventually be a way to know which colors
632 * couldn't be allocated and try to find a replacement */
633 p_vout->p_set_palette( p_vout, red, green, blue, transp );
635 p_vout->i_white_pixel = 0xff;
636 p_vout->i_black_pixel = 0x00;
637 p_vout->i_gray_pixel = 0x44;
638 p_vout->i_blue_pixel = 0x3b;
641 /* this loop allocates colors that got outside
643 for ( y = 0; y <= 256; y += 16 )
645 for ( u = 0; u <= 256; u += 32 )
646 for ( v = 0; v <= 256; v += 32 )
649 int dist, mindist = 100000000;
651 if( lookup[i] || y==0)
658 for( u2 = 0; u2 <= 256; u2 += 32 )
659 for( v2 = 0; v2 <= 256; v2 += 32 )
661 j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
662 dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
664 /* find the nearest color */
667 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
672 /* find the nearest color */
673 if( dist + 128 < mindist )
675 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
676 mindist = dist + 128;
687 p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
688 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
690 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
691 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
693 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
695 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
696 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
698 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
700 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
701 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
703 for( i_index = 0; i_index < 256; i_index++ )
705 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
706 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
707 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
712 p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
713 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
715 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
716 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
718 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
720 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
721 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
723 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
725 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
726 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
728 for( i_index = 0; i_index < 256; i_index++ )
730 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
731 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
732 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
739 * Set functions pointers
741 if( p_vout->b_grayscale )
744 switch( p_vout->i_bytes_per_pixel )
747 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;
748 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;
749 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;
752 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
753 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
754 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
757 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
758 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
759 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
762 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
763 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
764 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
771 switch( p_vout->i_bytes_per_pixel )
774 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
775 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
776 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
779 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB16;
780 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB16;
781 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB16;
784 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB24;
785 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB24;
786 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB24;
789 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB32;
790 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB32;
791 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB32;
797 /*****************************************************************************
798 * SetOffset: build offset array for conversion functions
799 *****************************************************************************
800 * This function will build an offset array used in later conversion functions.
801 * It will also set horizontal and vertical scaling indicators.
802 *****************************************************************************/
803 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
804 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
806 int i_x; /* x position in destination */
807 int i_scale_count; /* modulo counter */
810 * Prepare horizontal offset array
812 if( i_pic_width - i_width > 0 )
814 /* Prepare scaling array for horizontal extension */
816 i_scale_count = i_pic_width;
817 for( i_x = i_width; i_x--; )
819 while( (i_scale_count -= i_width) > 0 )
824 i_scale_count += i_pic_width;
827 else if( i_pic_width - i_width < 0 )
829 /* Prepare scaling array for horizontal reduction */
831 i_scale_count = i_pic_width;
832 for( i_x = i_pic_width; i_x--; )
835 while( (i_scale_count -= i_pic_width) >= 0 )
840 i_scale_count += i_width;
845 /* No horizontal scaling: YUV conversion is done directly to picture */
850 * Set vertical scaling indicator
852 if( i_pic_height - i_height > 0 )
856 else if( i_pic_height - i_height < 0 )
866 /*****************************************************************************
867 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
868 *****************************************************************************/
869 static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
870 yuv_data_t *p_u, yuv_data_t *p_v, int i_width,
871 int i_height, int i_pic_width, int i_pic_height,
872 int i_pic_line_width, int i_matrix_coefficients )
874 boolean_t b_horizontal_scaling; /* horizontal scaling type */
875 int i_vertical_scaling; /* vertical scaling type */
876 int i_x, i_y; /* horizontal and vertical indexes */
877 int i_scale_count; /* scale modulo counter */
878 int i_chroma_width; /* chroma width, not used */
879 u8 * p_gray; /* base conversion table */
880 u8 * p_pic_start; /* beginning of the current line for copy */
881 u8 * p_buffer_start; /* conversion buffer start */
882 u8 * p_buffer; /* conversion buffer pointer */
883 int * p_offset_start; /* offset array start */
884 int * p_offset; /* offset array pointer */
887 * Initialize some values - i_pic_line_width will store the line skip
889 i_pic_line_width -= i_pic_width;
890 p_gray = p_vout->yuv.yuv.p_gray8;
891 p_buffer_start = p_vout->yuv.p_buffer;
892 p_offset_start = p_vout->yuv.p_offset;
893 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
894 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
899 i_scale_count = i_pic_height;
900 for( i_y = 0; i_y < i_height; i_y++ )
902 /* Mark beginnning of line for possible later line copy, and initialize
905 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
907 /* Do YUV conversion to buffer - YUV picture is always formed of 16
908 * pixels wide blocks */
909 for( i_x = i_width / 16; i_x--; )
911 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
912 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
913 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
914 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
915 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
916 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
917 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
918 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
921 /* Do horizontal and vertical scaling */
923 SCALE_HEIGHT(400, 1);
927 /*****************************************************************************
928 * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
929 *****************************************************************************/
930 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,
931 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
932 int i_matrix_coefficients )
934 boolean_t b_horizontal_scaling; /* horizontal scaling type */
935 int i_vertical_scaling; /* vertical scaling type */
936 int i_x, i_y; /* horizontal and vertical indexes */
937 int i_scale_count; /* scale modulo counter */
938 int i_chroma_width; /* chroma width, not used */
939 u16 * p_gray; /* base conversion table */
940 u16 * p_pic_start; /* beginning of the current line for copy */
941 u16 * p_buffer_start; /* conversion buffer start */
942 u16 * p_buffer; /* conversion buffer pointer */
943 int * p_offset_start; /* offset array start */
944 int * p_offset; /* offset array pointer */
947 * Initialize some values - i_pic_line_width will store the line skip
949 i_pic_line_width -= i_pic_width;
950 p_gray = p_vout->yuv.yuv.p_gray16;
951 p_buffer_start = p_vout->yuv.p_buffer;
952 p_offset_start = p_vout->yuv.p_offset;
953 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
954 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
959 i_scale_count = i_pic_height;
960 for( i_y = 0; i_y < i_height; i_y++ )
962 /* Mark beginnning of line for possible later line copy, and initialize
965 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
967 /* Do YUV conversion to buffer - YUV picture is always formed of 16
968 * pixels wide blocks */
969 for( i_x = i_width / 16; i_x--; )
971 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
972 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
973 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
974 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
975 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
976 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
977 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
978 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
981 /* Do horizontal and vertical scaling */
983 SCALE_HEIGHT(400, 2);
987 /*****************************************************************************
988 * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 3 Bpp
989 *****************************************************************************/
990 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,
991 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
992 int i_matrix_coefficients )
997 /*****************************************************************************
998 * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
999 *****************************************************************************/
1000 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,
1001 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1002 int i_matrix_coefficients )
1004 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1005 int i_vertical_scaling; /* vertical scaling type */
1006 int i_x, i_y; /* horizontal and vertical indexes */
1007 int i_scale_count; /* scale modulo counter */
1008 int i_chroma_width; /* chroma width, not used */
1009 u32 * p_gray; /* base conversion table */
1010 u32 * p_pic_start; /* beginning of the current line for copy */
1011 u32 * p_buffer_start; /* conversion buffer start */
1012 u32 * p_buffer; /* conversion buffer pointer */
1013 int * p_offset_start; /* offset array start */
1014 int * p_offset; /* offset array pointer */
1017 * Initialize some values - i_pic_line_width will store the line skip
1019 i_pic_line_width -= i_pic_width;
1020 p_gray = p_vout->yuv.yuv.p_gray32;
1021 p_buffer_start = p_vout->yuv.p_buffer;
1022 p_offset_start = p_vout->yuv.p_offset;
1023 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1024 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1027 * Perform conversion
1029 i_scale_count = i_pic_height;
1030 for( i_y = 0; i_y < i_height; i_y++ )
1032 /* Mark beginnning of line for possible later line copy, and initialize
1034 p_pic_start = p_pic;
1035 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1037 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1038 * pixels wide blocks */
1039 for( i_x = i_width / 16; i_x--; )
1041 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1042 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1043 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1044 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1045 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1046 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1047 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1048 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1051 /* Do horizontal and vertical scaling */
1053 SCALE_HEIGHT(400, 4);
1057 /*****************************************************************************
1058 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
1059 *****************************************************************************/
1060 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,
1061 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1062 int i_matrix_coefficients )
1064 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1065 int i_vertical_scaling; /* vertical scaling type */
1066 int i_x, i_y; /* horizontal and vertical indexes */
1067 int i_scale_count; /* scale modulo counter */
1068 int b_jump_uv; /* should we jump u and v ? */
1069 int i_real_y; /* y % 4 */
1070 u8 * p_lookup; /* lookup table */
1071 int i_chroma_width; /* chroma width */
1072 int * p_offset_start; /* offset array start */
1073 int * p_offset; /* offset array pointer */
1075 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
1076 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
1077 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
1078 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
1080 int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
1081 int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
1082 int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
1083 int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
1085 /* other matrices that can be interesting, either for debugging or for effects */
1087 int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
1088 int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
1089 int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
1090 int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
1091 int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
1092 int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
1096 * Initialize some values - i_pic_line_width will store the line skip
1098 i_pic_line_width -= i_pic_width;
1099 i_chroma_width = i_width / 2;
1100 p_offset_start = p_vout->yuv.p_offset;
1101 p_lookup = p_vout->yuv.p_base;
1102 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1103 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1106 * Perform conversion
1108 i_scale_count = i_pic_height;
1110 for( i_y = 0; i_y < i_height; i_y++ )
1112 /* Do horizontal and vertical scaling */
1113 SCALE_WIDTH_DITHER( 420 );
1114 SCALE_HEIGHT_DITHER( 420 );
1118 /*****************************************************************************
1119 * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1120 *****************************************************************************/
1121 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,
1122 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1123 int i_matrix_coefficients )
1125 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1126 int i_vertical_scaling; /* vertical scaling type */
1127 int i_x, i_y; /* horizontal and vertical indexes */
1128 int i_scale_count; /* scale modulo counter */
1129 int i_uval, i_vval; /* U and V samples */
1130 int i_red, i_green, i_blue; /* U and V modified samples */
1131 int i_chroma_width; /* chroma width */
1132 u8 * p_yuv; /* base conversion table */
1133 u8 * p_ybase; /* Y dependant conversion table */
1134 u8 * p_pic_start; /* beginning of the current line for copy */
1135 u8 * p_buffer_start; /* conversion buffer start */
1136 u8 * p_buffer; /* conversion buffer pointer */
1137 int * p_offset_start; /* offset array start */
1138 int * p_offset; /* offset array pointer */
1141 * Initialize some values - i_pic_line_width will store the line skip
1143 i_pic_line_width -= i_pic_width;
1144 i_chroma_width = i_width / 2;
1145 p_yuv = p_vout->yuv.yuv.p_rgb8;
1146 p_buffer_start = p_vout->yuv.p_buffer;
1147 p_offset_start = p_vout->yuv.p_offset;
1148 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1149 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1152 * Perform conversion
1154 i_scale_count = i_pic_height;
1155 for( i_y = 0; i_y < i_height; i_y++ )
1157 /* Mark beginnning of line for possible later line copy, and initialize
1159 p_pic_start = p_pic;
1160 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1162 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1163 * pixels wide blocks */
1164 for( i_x = i_width / 16; i_x--; )
1166 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1167 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1168 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1169 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1170 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1171 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1172 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1173 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1176 /* Do horizontal and vertical scaling */
1178 SCALE_HEIGHT(422, 1);
1182 /*****************************************************************************
1183 * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1184 *****************************************************************************/
1185 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,
1186 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1187 int i_matrix_coefficients )
1189 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1190 int i_vertical_scaling; /* vertical scaling type */
1191 int i_x, i_y; /* horizontal and vertical indexes */
1192 int i_scale_count; /* scale modulo counter */
1193 int i_uval, i_vval; /* U and V samples */
1194 int i_red, i_green, i_blue; /* U and V modified samples */
1195 int i_chroma_width; /* chroma width, not used */
1196 u8 * p_yuv; /* base conversion table */
1197 u8 * p_ybase; /* Y dependant conversion table */
1198 u8 * p_pic_start; /* beginning of the current line for copy */
1199 u8 * p_buffer_start; /* conversion buffer start */
1200 u8 * p_buffer; /* conversion buffer pointer */
1201 int * p_offset_start; /* offset array start */
1202 int * p_offset; /* offset array pointer */
1205 * Initialize some values - i_pic_line_width will store the line skip
1207 i_pic_line_width -= i_pic_width;
1208 p_yuv = p_vout->yuv.yuv.p_rgb8;
1209 p_buffer_start = p_vout->yuv.p_buffer;
1210 p_offset_start = p_vout->yuv.p_offset;
1211 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1212 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1215 * Perform conversion
1217 i_scale_count = i_pic_height;
1218 for( i_y = 0; i_y < i_height; i_y++ )
1220 /* Mark beginnning of line for possible later line copy, and initialize
1222 p_pic_start = p_pic;
1223 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1225 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1226 * pixels wide blocks */
1227 for( i_x = i_width / 16; i_x--; )
1229 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1230 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1231 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1232 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1233 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1234 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1235 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1236 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1239 /* Do horizontal and vertical scaling */
1241 SCALE_HEIGHT(444, 1);
1245 /*****************************************************************************
1246 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1247 *****************************************************************************/
1248 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,
1249 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1250 int i_matrix_coefficients )
1254 int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
1256 i_chroma_width = i_width / 2;
1257 i_chroma_skip = i_skip / 2;
1258 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1259 (i_width + i_skip) * sizeof( yuv_data_t ),
1260 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1261 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1262 p_vout->i_screen_depth == 15 );
1264 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1265 int i_vertical_scaling; /* vertical scaling type */
1266 int i_x, i_y; /* horizontal and vertical indexes */
1267 int i_scale_count; /* scale modulo counter */
1268 int i_uval, i_vval; /* U and V samples */
1269 int i_red, i_green, i_blue; /* U and V modified samples */
1270 int i_chroma_width; /* chroma width */
1271 u16 * p_yuv; /* base conversion table */
1272 u16 * p_ybase; /* Y dependant conversion table */
1273 u16 * p_pic_start; /* beginning of the current line for copy */
1274 u16 * p_buffer_start; /* conversion buffer start */
1275 u16 * p_buffer; /* conversion buffer pointer */
1276 int * p_offset_start; /* offset array start */
1277 int * p_offset; /* offset array pointer */
1280 * Initialize some values - i_pic_line_width will store the line skip
1282 i_pic_line_width -= i_pic_width;
1283 i_chroma_width = i_width / 2;
1284 p_yuv = p_vout->yuv.yuv.p_rgb16;
1285 p_buffer_start = p_vout->yuv.p_buffer;
1286 p_offset_start = p_vout->yuv.p_offset;
1287 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1288 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1291 * Perform conversion
1293 i_scale_count = i_pic_height;
1294 for( i_y = 0; i_y < i_height; i_y++ )
1296 /* Mark beginnning of line for possible later line copy, and initialize
1298 p_pic_start = p_pic;
1299 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1301 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1302 * pixels wide blocks */
1303 for( i_x = i_width / 16; i_x--; )
1305 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1306 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1307 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1308 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1309 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1310 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1311 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1312 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1315 /* Do horizontal and vertical scaling */
1317 SCALE_HEIGHT(420, 2);
1321 /*****************************************************************************
1322 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1323 *****************************************************************************/
1324 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,
1325 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1326 int i_matrix_coefficients )
1328 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1329 int i_vertical_scaling; /* vertical scaling type */
1330 int i_x, i_y; /* horizontal and vertical indexes */
1331 int i_scale_count; /* scale modulo counter */
1332 int i_uval, i_vval; /* U and V samples */
1333 int i_red, i_green, i_blue; /* U and V modified samples */
1334 int i_chroma_width; /* chroma width */
1335 u16 * p_yuv; /* base conversion table */
1336 u16 * p_ybase; /* Y dependant conversion table */
1337 u16 * p_pic_start; /* beginning of the current line for copy */
1338 u16 * p_buffer_start; /* conversion buffer start */
1339 u16 * p_buffer; /* conversion buffer pointer */
1340 int * p_offset_start; /* offset array start */
1341 int * p_offset; /* offset array pointer */
1344 * Initialize some values - i_pic_line_width will store the line skip
1346 i_pic_line_width -= i_pic_width;
1347 i_chroma_width = i_width / 2;
1348 p_yuv = p_vout->yuv.yuv.p_rgb16;
1349 p_buffer_start = p_vout->yuv.p_buffer;
1350 p_offset_start = p_vout->yuv.p_offset;
1351 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1352 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1355 * Perform conversion
1357 i_scale_count = i_pic_height;
1358 for( i_y = 0; i_y < i_height; i_y++ )
1360 /* Mark beginnning of line for possible later line copy, and initialize
1362 p_pic_start = p_pic;
1363 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1365 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1366 * pixels wide blocks */
1367 for( i_x = i_width / 16; i_x--; )
1369 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1370 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1371 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1372 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1373 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1374 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1375 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1376 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1379 /* Do horizontal and vertical scaling */
1381 SCALE_HEIGHT(422, 2);
1385 /*****************************************************************************
1386 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1387 *****************************************************************************/
1388 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,
1389 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1390 int i_matrix_coefficients )
1392 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1393 int i_vertical_scaling; /* vertical scaling type */
1394 int i_x, i_y; /* horizontal and vertical indexes */
1395 int i_scale_count; /* scale modulo counter */
1396 int i_uval, i_vval; /* U and V samples */
1397 int i_red, i_green, i_blue; /* U and V modified samples */
1398 int i_chroma_width; /* chroma width, not used */
1399 u16 * p_yuv; /* base conversion table */
1400 u16 * p_ybase; /* Y dependant conversion table */
1401 u16 * p_pic_start; /* beginning of the current line for copy */
1402 u16 * p_buffer_start; /* conversion buffer start */
1403 u16 * p_buffer; /* conversion buffer pointer */
1404 int * p_offset_start; /* offset array start */
1405 int * p_offset; /* offset array pointer */
1408 * Initialize some values - i_pic_line_width will store the line skip
1410 i_pic_line_width -= i_pic_width;
1411 p_yuv = p_vout->yuv.yuv.p_rgb16;
1412 p_buffer_start = p_vout->yuv.p_buffer;
1413 p_offset_start = p_vout->yuv.p_offset;
1414 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1415 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1418 * Perform conversion
1420 i_scale_count = i_pic_height;
1421 for( i_y = 0; i_y < i_height; i_y++ )
1423 /* Mark beginnning of line for possible later line copy, and initialize
1425 p_pic_start = p_pic;
1426 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1428 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1429 * pixels wide blocks */
1430 for( i_x = i_width / 16; i_x--; )
1432 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1433 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1434 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1435 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1436 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1437 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1438 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1439 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1442 /* Do horizontal and vertical scaling */
1444 SCALE_HEIGHT(444, 2);
1448 /*****************************************************************************
1449 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1450 *****************************************************************************/
1451 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,
1452 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1453 int i_matrix_coefficients )
1458 /*****************************************************************************
1459 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1460 *****************************************************************************/
1461 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,
1462 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1463 int i_matrix_coefficients )
1468 /*****************************************************************************
1469 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1470 *****************************************************************************/
1471 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,
1472 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1473 int i_matrix_coefficients )
1478 /*****************************************************************************
1479 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1480 *****************************************************************************/
1481 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,
1482 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1483 int i_matrix_coefficients )
1485 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1486 int i_vertical_scaling; /* vertical scaling type */
1487 int i_x, i_y; /* horizontal and vertical indexes */
1488 int i_scale_count; /* scale modulo counter */
1489 int i_uval, i_vval; /* U and V samples */
1490 int i_red, i_green, i_blue; /* U and V modified samples */
1491 int i_chroma_width; /* chroma width */
1492 u32 * p_yuv; /* base conversion table */
1493 u32 * p_ybase; /* Y dependant conversion table */
1494 u32 * p_pic_start; /* beginning of the current line for copy */
1495 u32 * p_buffer_start; /* conversion buffer start */
1496 u32 * p_buffer; /* conversion buffer pointer */
1497 int * p_offset_start; /* offset array start */
1498 int * p_offset; /* offset array pointer */
1501 * Initialize some values - i_pic_line_width will store the line skip
1503 i_pic_line_width -= i_pic_width;
1504 i_chroma_width = i_width / 2;
1505 p_yuv = p_vout->yuv.yuv.p_rgb32;
1506 p_buffer_start = p_vout->yuv.p_buffer;
1507 p_offset_start = p_vout->yuv.p_offset;
1508 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1509 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1512 * Perform conversion
1514 i_scale_count = i_pic_height;
1515 for( i_y = 0; i_y < i_height; i_y++ )
1517 /* Mark beginnning of line for possible later line copy, and initialize
1519 p_pic_start = p_pic;
1520 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1522 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1523 * pixels wide blocks */
1524 for( i_x = i_width / 16; i_x--; )
1526 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1527 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1528 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1529 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1530 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1531 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1532 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1533 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1536 /* Do horizontal and vertical scaling */
1538 SCALE_HEIGHT(420, 4);
1542 /*****************************************************************************
1543 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1544 *****************************************************************************/
1545 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,
1546 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1547 int i_matrix_coefficients )
1549 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1550 int i_vertical_scaling; /* vertical scaling type */
1551 int i_x, i_y; /* horizontal and vertical indexes */
1552 int i_scale_count; /* scale modulo counter */
1553 int i_uval, i_vval; /* U and V samples */
1554 int i_red, i_green, i_blue; /* U and V modified samples */
1555 int i_chroma_width; /* chroma width */
1556 u32 * p_yuv; /* base conversion table */
1557 u32 * p_ybase; /* Y dependant conversion table */
1558 u32 * p_pic_start; /* beginning of the current line for copy */
1559 u32 * p_buffer_start; /* conversion buffer start */
1560 u32 * p_buffer; /* conversion buffer pointer */
1561 int * p_offset_start; /* offset array start */
1562 int * p_offset; /* offset array pointer */
1565 * Initialize some values - i_pic_line_width will store the line skip
1567 i_pic_line_width -= i_pic_width;
1568 i_chroma_width = i_width / 2;
1569 p_yuv = p_vout->yuv.yuv.p_rgb32;
1570 p_buffer_start = p_vout->yuv.p_buffer;
1571 p_offset_start = p_vout->yuv.p_offset;
1572 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1573 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1576 * Perform conversion
1578 i_scale_count = i_pic_height;
1579 for( i_y = 0; i_y < i_height; i_y++ )
1581 /* Mark beginnning of line for possible later line copy, and initialize
1583 p_pic_start = p_pic;
1584 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1586 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1587 * pixels wide blocks */
1588 for( i_x = i_width / 16; i_x--; )
1590 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1591 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1592 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1593 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1594 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1595 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1596 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1597 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1600 /* Do horizontal and vertical scaling */
1602 SCALE_HEIGHT(422, 4);
1606 /*****************************************************************************
1607 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1608 *****************************************************************************/
1609 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,
1610 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1611 int i_matrix_coefficients )
1613 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1614 int i_vertical_scaling; /* vertical scaling type */
1615 int i_x, i_y; /* horizontal and vertical indexes */
1616 int i_scale_count; /* scale modulo counter */
1617 int i_uval, i_vval; /* U and V samples */
1618 int i_red, i_green, i_blue; /* U and V modified samples */
1619 int i_chroma_width; /* chroma width, not used */
1620 u32 * p_yuv; /* base conversion table */
1621 u32 * p_ybase; /* Y dependant conversion table */
1622 u32 * p_pic_start; /* beginning of the current line for copy */
1623 u32 * p_buffer_start; /* conversion buffer start */
1624 u32 * p_buffer; /* conversion buffer pointer */
1625 int * p_offset_start; /* offset array start */
1626 int * p_offset; /* offset array pointer */
1629 * Initialize some values - i_pic_line_width will store the line skip
1631 i_pic_line_width -= i_pic_width;
1632 p_yuv = p_vout->yuv.yuv.p_rgb32;
1633 p_buffer_start = p_vout->yuv.p_buffer;
1634 p_offset_start = p_vout->yuv.p_offset;
1635 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1636 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1639 * Perform conversion
1641 i_scale_count = i_pic_height;
1642 for( i_y = 0; i_y < i_height; i_y++ )
1644 /* Mark beginnning of line for possible later line copy, and initialize
1646 p_pic_start = p_pic;
1647 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1649 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1650 * pixels wide blocks */
1651 for( i_x = i_width / 16; i_x--; )
1653 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1654 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1655 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1656 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1657 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1658 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1659 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1660 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1663 /* Do horizontal and vertical scaling */
1665 SCALE_HEIGHT(444, 4);
1669 /*-------------------- walken code follows ----------------------------------*/
1672 * YUV to RGB routines.
1674 * these routines calculate r, g and b values from each pixel's y, u and v.
1675 * these r, g an b values are then passed thru a table lookup to take the
1676 * gamma curve into account and find the corresponding pixel value.
1678 * the table must store more than 3*256 values because of the possibility
1679 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1680 * values are in the following intervals :
1681 * -176 to 255+176 for red
1682 * -133 to 255+133 for green
1683 * -222 to 255+222 for blue
1685 * If the input y,u,v values are right, the r,g,b results are not expected
1686 * to move out of the 0 to 255 interval but who knows what will happen in
1689 * the red, green and blue conversion tables are stored in a single 1935-entry
1690 * array. The respective positions of each component in the array have been
1691 * calculated to minimize the cache interactions of the 3 tables.
1696 static void yuvToRgb24 (unsigned char * Y,
1697 unsigned char * U, unsigned char * V,
1698 char * dest, int table[1935], int width)
1713 uvRed = (V_RED_COEF*v) >> SHIFT;
1714 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1715 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1717 tableY = table + *(Y++);
1718 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1719 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1721 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1723 *(dest++) = tmp24 >> 8;
1724 *(dest++) = tmp24 >> 16;
1726 tableY = table + *(Y++);
1727 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1728 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1730 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1732 *(dest++) = tmp24 >> 8;
1733 *(dest++) = tmp24 >> 16;
1737 uvRed = (V_RED_COEF*v) >> SHIFT;
1738 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1739 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1741 tableY = table + *(Y++);
1742 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1743 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1745 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1747 *(dest++) = tmp24 >> 8;
1748 *(dest++) = tmp24 >> 16;
1750 tableY = table + *(Y++);
1751 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1752 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1754 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1756 *(dest++) = tmp24 >> 8;
1757 *(dest++) = tmp24 >> 16;
1761 uvRed = (V_RED_COEF*v) >> SHIFT;
1762 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1763 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1765 tableY = table + *(Y++);
1766 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1767 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1769 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1771 *(dest++) = tmp24 >> 8;
1772 *(dest++) = tmp24 >> 16;
1774 tableY = table + *(Y++);
1775 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1776 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1778 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1780 *(dest++) = tmp24 >> 8;
1781 *(dest++) = tmp24 >> 16;
1785 uvRed = (V_RED_COEF*v) >> SHIFT;
1786 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1787 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1789 tableY = table + *(Y++);
1790 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1791 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1793 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1795 *(dest++) = tmp24 >> 8;
1796 *(dest++) = tmp24 >> 16;
1798 tableY = table + *(Y++);
1799 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1800 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1802 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1804 *(dest++) = tmp24 >> 8;
1805 *(dest++) = tmp24 >> 16;
1808 i = (width & 7) >> 1;
1812 uvRed = (V_RED_COEF*v) >> SHIFT;
1813 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1814 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1816 tableY = table + *(Y++);
1817 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1818 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1820 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1822 *(dest++) = tmp24 >> 8;
1823 *(dest++) = tmp24 >> 16;
1825 tableY = table + *(Y++);
1826 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1827 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1829 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1831 *(dest++) = tmp24 >> 8;
1832 *(dest++) = tmp24 >> 16;
1838 uvRed = (V_RED_COEF*v) >> SHIFT;
1839 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1840 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1842 tableY = table + *(Y++);
1843 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1844 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1846 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1848 *(dest++) = tmp24 >> 8;
1849 *(dest++) = tmp24 >> 16;