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 */
1086 //int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
1087 //int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
1088 //int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
1089 //int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
1090 //int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
1091 //int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
1094 * Initialize some values - i_pic_line_width will store the line skip
1096 i_pic_line_width -= i_pic_width;
1097 i_chroma_width = i_width / 2;
1098 p_offset_start = p_vout->yuv.p_offset;
1099 p_lookup = p_vout->yuv.p_base;
1100 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1101 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1104 * Perform conversion
1106 i_scale_count = i_pic_height;
1108 for( i_y = 0; i_y < i_height; i_y++ )
1110 /* Do horizontal and vertical scaling */
1111 SCALE_WIDTH_DITHER( 420 );
1112 SCALE_HEIGHT_DITHER( 420 );
1116 /*****************************************************************************
1117 * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1118 *****************************************************************************/
1119 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,
1120 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1121 int i_matrix_coefficients )
1123 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1124 int i_vertical_scaling; /* vertical scaling type */
1125 int i_x, i_y; /* horizontal and vertical indexes */
1126 int i_scale_count; /* scale modulo counter */
1127 int i_uval, i_vval; /* U and V samples */
1128 int i_red, i_green, i_blue; /* U and V modified samples */
1129 int i_chroma_width; /* chroma width */
1130 u8 * p_yuv; /* base conversion table */
1131 u8 * p_ybase; /* Y dependant conversion table */
1132 u8 * p_pic_start; /* beginning of the current line for copy */
1133 u8 * p_buffer_start; /* conversion buffer start */
1134 u8 * p_buffer; /* conversion buffer pointer */
1135 int * p_offset_start; /* offset array start */
1136 int * p_offset; /* offset array pointer */
1139 * Initialize some values - i_pic_line_width will store the line skip
1141 i_pic_line_width -= i_pic_width;
1142 i_chroma_width = i_width / 2;
1143 p_yuv = p_vout->yuv.yuv.p_rgb8;
1144 p_buffer_start = p_vout->yuv.p_buffer;
1145 p_offset_start = p_vout->yuv.p_offset;
1146 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1147 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1150 * Perform conversion
1152 i_scale_count = i_pic_height;
1153 for( i_y = 0; i_y < i_height; i_y++ )
1155 /* Mark beginnning of line for possible later line copy, and initialize
1157 p_pic_start = p_pic;
1158 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1160 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1161 * pixels wide blocks */
1162 for( i_x = i_width / 16; i_x--; )
1164 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1165 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
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);
1174 /* Do horizontal and vertical scaling */
1176 SCALE_HEIGHT(422, 1);
1180 /*****************************************************************************
1181 * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1182 *****************************************************************************/
1183 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,
1184 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1185 int i_matrix_coefficients )
1187 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1188 int i_vertical_scaling; /* vertical scaling type */
1189 int i_x, i_y; /* horizontal and vertical indexes */
1190 int i_scale_count; /* scale modulo counter */
1191 int i_uval, i_vval; /* U and V samples */
1192 int i_red, i_green, i_blue; /* U and V modified samples */
1193 int i_chroma_width; /* chroma width, not used */
1194 u8 * p_yuv; /* base conversion table */
1195 u8 * p_ybase; /* Y dependant conversion table */
1196 u8 * p_pic_start; /* beginning of the current line for copy */
1197 u8 * p_buffer_start; /* conversion buffer start */
1198 u8 * p_buffer; /* conversion buffer pointer */
1199 int * p_offset_start; /* offset array start */
1200 int * p_offset; /* offset array pointer */
1203 * Initialize some values - i_pic_line_width will store the line skip
1205 i_pic_line_width -= i_pic_width;
1206 p_yuv = p_vout->yuv.yuv.p_rgb8;
1207 p_buffer_start = p_vout->yuv.p_buffer;
1208 p_offset_start = p_vout->yuv.p_offset;
1209 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1210 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1213 * Perform conversion
1215 i_scale_count = i_pic_height;
1216 for( i_y = 0; i_y < i_height; i_y++ )
1218 /* Mark beginnning of line for possible later line copy, and initialize
1220 p_pic_start = p_pic;
1221 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1223 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1224 * pixels wide blocks */
1225 for( i_x = i_width / 16; i_x--; )
1227 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1228 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
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);
1237 /* Do horizontal and vertical scaling */
1239 SCALE_HEIGHT(444, 1);
1243 /*****************************************************************************
1244 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1245 *****************************************************************************/
1246 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,
1247 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1248 int i_matrix_coefficients )
1251 // int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
1253 i_chroma_width = i_width / 2;
1254 i_chroma_skip = i_skip / 2;
1255 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1256 (i_width + i_skip) * sizeof( yuv_data_t ),
1257 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1258 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1259 p_vout->i_screen_depth == 15 );
1261 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1262 int i_vertical_scaling; /* vertical scaling type */
1263 int i_x, i_y; /* horizontal and vertical indexes */
1264 int i_scale_count; /* scale modulo counter */
1265 int i_uval, i_vval; /* U and V samples */
1266 int i_red, i_green, i_blue; /* U and V modified samples */
1267 int i_chroma_width; /* chroma width */
1268 u16 * p_yuv; /* base conversion table */
1269 u16 * p_ybase; /* Y dependant conversion table */
1270 u16 * p_pic_start; /* beginning of the current line for copy */
1271 u16 * p_buffer_start; /* conversion buffer start */
1272 u16 * p_buffer; /* conversion buffer pointer */
1273 int * p_offset_start; /* offset array start */
1274 int * p_offset; /* offset array pointer */
1277 * Initialize some values - i_pic_line_width will store the line skip
1279 i_pic_line_width -= i_pic_width;
1280 i_chroma_width = i_width / 2;
1281 p_yuv = p_vout->yuv.yuv.p_rgb16;
1282 p_buffer_start = p_vout->yuv.p_buffer;
1283 p_offset_start = p_vout->yuv.p_offset;
1284 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1285 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1288 * Perform conversion
1290 i_scale_count = i_pic_height;
1291 for( i_y = 0; i_y < i_height; i_y++ )
1293 /* Mark beginnning of line for possible later line copy, and initialize
1295 p_pic_start = p_pic;
1296 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1298 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1299 * pixels wide blocks */
1300 for( i_x = i_width / 16; i_x--; )
1302 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1303 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1304 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
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);
1312 /* Do horizontal and vertical scaling */
1314 SCALE_HEIGHT(420, 2);
1318 /*****************************************************************************
1319 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1320 *****************************************************************************/
1321 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,
1322 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1323 int i_matrix_coefficients )
1325 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1326 int i_vertical_scaling; /* vertical scaling type */
1327 int i_x, i_y; /* horizontal and vertical indexes */
1328 int i_scale_count; /* scale modulo counter */
1329 int i_uval, i_vval; /* U and V samples */
1330 int i_red, i_green, i_blue; /* U and V modified samples */
1331 int i_chroma_width; /* chroma width */
1332 u16 * p_yuv; /* base conversion table */
1333 u16 * p_ybase; /* Y dependant conversion table */
1334 u16 * p_pic_start; /* beginning of the current line for copy */
1335 u16 * p_buffer_start; /* conversion buffer start */
1336 u16 * p_buffer; /* conversion buffer pointer */
1337 int * p_offset_start; /* offset array start */
1338 int * p_offset; /* offset array pointer */
1341 * Initialize some values - i_pic_line_width will store the line skip
1343 i_pic_line_width -= i_pic_width;
1344 i_chroma_width = i_width / 2;
1345 p_yuv = p_vout->yuv.yuv.p_rgb16;
1346 p_buffer_start = p_vout->yuv.p_buffer;
1347 p_offset_start = p_vout->yuv.p_offset;
1348 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1349 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1352 * Perform conversion
1354 i_scale_count = i_pic_height;
1355 for( i_y = 0; i_y < i_height; i_y++ )
1357 /* Mark beginnning of line for possible later line copy, and initialize
1359 p_pic_start = p_pic;
1360 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1362 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1363 * pixels wide blocks */
1364 for( i_x = i_width / 16; i_x--; )
1366 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1367 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1368 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
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);
1376 /* Do horizontal and vertical scaling */
1378 SCALE_HEIGHT(422, 2);
1382 /*****************************************************************************
1383 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1384 *****************************************************************************/
1385 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,
1386 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1387 int i_matrix_coefficients )
1389 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1390 int i_vertical_scaling; /* vertical scaling type */
1391 int i_x, i_y; /* horizontal and vertical indexes */
1392 int i_scale_count; /* scale modulo counter */
1393 int i_uval, i_vval; /* U and V samples */
1394 int i_red, i_green, i_blue; /* U and V modified samples */
1395 int i_chroma_width; /* chroma width, not used */
1396 u16 * p_yuv; /* base conversion table */
1397 u16 * p_ybase; /* Y dependant conversion table */
1398 u16 * p_pic_start; /* beginning of the current line for copy */
1399 u16 * p_buffer_start; /* conversion buffer start */
1400 u16 * p_buffer; /* conversion buffer pointer */
1401 int * p_offset_start; /* offset array start */
1402 int * p_offset; /* offset array pointer */
1405 * Initialize some values - i_pic_line_width will store the line skip
1407 i_pic_line_width -= i_pic_width;
1408 p_yuv = p_vout->yuv.yuv.p_rgb16;
1409 p_buffer_start = p_vout->yuv.p_buffer;
1410 p_offset_start = p_vout->yuv.p_offset;
1411 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1412 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1415 * Perform conversion
1417 i_scale_count = i_pic_height;
1418 for( i_y = 0; i_y < i_height; i_y++ )
1420 /* Mark beginnning of line for possible later line copy, and initialize
1422 p_pic_start = p_pic;
1423 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1425 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1426 * pixels wide blocks */
1427 for( i_x = i_width / 16; i_x--; )
1429 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1430 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1431 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
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);
1439 /* Do horizontal and vertical scaling */
1441 SCALE_HEIGHT(444, 2);
1445 /*****************************************************************************
1446 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1447 *****************************************************************************/
1448 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,
1449 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1450 int i_matrix_coefficients )
1455 /*****************************************************************************
1456 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1457 *****************************************************************************/
1458 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,
1459 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1460 int i_matrix_coefficients )
1465 /*****************************************************************************
1466 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1467 *****************************************************************************/
1468 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,
1469 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1470 int i_matrix_coefficients )
1475 /*****************************************************************************
1476 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1477 *****************************************************************************/
1478 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,
1479 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1480 int i_matrix_coefficients )
1482 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1483 int i_vertical_scaling; /* vertical scaling type */
1484 int i_x, i_y; /* horizontal and vertical indexes */
1485 int i_scale_count; /* scale modulo counter */
1486 int i_uval, i_vval; /* U and V samples */
1487 int i_red, i_green, i_blue; /* U and V modified samples */
1488 int i_chroma_width; /* chroma width */
1489 u32 * p_yuv; /* base conversion table */
1490 u32 * p_ybase; /* Y dependant conversion table */
1491 u32 * p_pic_start; /* beginning of the current line for copy */
1492 u32 * p_buffer_start; /* conversion buffer start */
1493 u32 * p_buffer; /* conversion buffer pointer */
1494 int * p_offset_start; /* offset array start */
1495 int * p_offset; /* offset array pointer */
1498 * Initialize some values - i_pic_line_width will store the line skip
1500 i_pic_line_width -= i_pic_width;
1501 i_chroma_width = i_width / 2;
1502 p_yuv = p_vout->yuv.yuv.p_rgb32;
1503 p_buffer_start = p_vout->yuv.p_buffer;
1504 p_offset_start = p_vout->yuv.p_offset;
1505 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1506 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1509 * Perform conversion
1511 i_scale_count = i_pic_height;
1512 for( i_y = 0; i_y < i_height; i_y++ )
1514 /* Mark beginnning of line for possible later line copy, and initialize
1516 p_pic_start = p_pic;
1517 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1519 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1520 * pixels wide blocks */
1521 for( i_x = i_width / 16; i_x--; )
1523 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1524 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1525 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
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);
1533 /* Do horizontal and vertical scaling */
1535 SCALE_HEIGHT(420, 4);
1539 /*****************************************************************************
1540 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1541 *****************************************************************************/
1542 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,
1543 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1544 int i_matrix_coefficients )
1546 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1547 int i_vertical_scaling; /* vertical scaling type */
1548 int i_x, i_y; /* horizontal and vertical indexes */
1549 int i_scale_count; /* scale modulo counter */
1550 int i_uval, i_vval; /* U and V samples */
1551 int i_red, i_green, i_blue; /* U and V modified samples */
1552 int i_chroma_width; /* chroma width */
1553 u32 * p_yuv; /* base conversion table */
1554 u32 * p_ybase; /* Y dependant conversion table */
1555 u32 * p_pic_start; /* beginning of the current line for copy */
1556 u32 * p_buffer_start; /* conversion buffer start */
1557 u32 * p_buffer; /* conversion buffer pointer */
1558 int * p_offset_start; /* offset array start */
1559 int * p_offset; /* offset array pointer */
1562 * Initialize some values - i_pic_line_width will store the line skip
1564 i_pic_line_width -= i_pic_width;
1565 i_chroma_width = i_width / 2;
1566 p_yuv = p_vout->yuv.yuv.p_rgb32;
1567 p_buffer_start = p_vout->yuv.p_buffer;
1568 p_offset_start = p_vout->yuv.p_offset;
1569 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1570 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1573 * Perform conversion
1575 i_scale_count = i_pic_height;
1576 for( i_y = 0; i_y < i_height; i_y++ )
1578 /* Mark beginnning of line for possible later line copy, and initialize
1580 p_pic_start = p_pic;
1581 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1583 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1584 * pixels wide blocks */
1585 for( i_x = i_width / 16; i_x--; )
1587 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1588 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1589 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
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);
1597 /* Do horizontal and vertical scaling */
1599 SCALE_HEIGHT(422, 4);
1603 /*****************************************************************************
1604 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1605 *****************************************************************************/
1606 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,
1607 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1608 int i_matrix_coefficients )
1610 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1611 int i_vertical_scaling; /* vertical scaling type */
1612 int i_x, i_y; /* horizontal and vertical indexes */
1613 int i_scale_count; /* scale modulo counter */
1614 int i_uval, i_vval; /* U and V samples */
1615 int i_red, i_green, i_blue; /* U and V modified samples */
1616 int i_chroma_width; /* chroma width, not used */
1617 u32 * p_yuv; /* base conversion table */
1618 u32 * p_ybase; /* Y dependant conversion table */
1619 u32 * p_pic_start; /* beginning of the current line for copy */
1620 u32 * p_buffer_start; /* conversion buffer start */
1621 u32 * p_buffer; /* conversion buffer pointer */
1622 int * p_offset_start; /* offset array start */
1623 int * p_offset; /* offset array pointer */
1626 * Initialize some values - i_pic_line_width will store the line skip
1628 i_pic_line_width -= i_pic_width;
1629 p_yuv = p_vout->yuv.yuv.p_rgb32;
1630 p_buffer_start = p_vout->yuv.p_buffer;
1631 p_offset_start = p_vout->yuv.p_offset;
1632 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1633 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1636 * Perform conversion
1638 i_scale_count = i_pic_height;
1639 for( i_y = 0; i_y < i_height; i_y++ )
1641 /* Mark beginnning of line for possible later line copy, and initialize
1643 p_pic_start = p_pic;
1644 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1646 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1647 * pixels wide blocks */
1648 for( i_x = i_width / 16; i_x--; )
1650 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1651 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1652 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
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);
1660 /* Do horizontal and vertical scaling */
1662 SCALE_HEIGHT(444, 4);
1666 //-------------------- walken code follows ------------------------------------
1669 * YUV to RGB routines.
1671 * these routines calculate r, g and b values from each pixel's y, u and v.
1672 * these r, g an b values are then passed thru a table lookup to take the
1673 * gamma curve into account and find the corresponding pixel value.
1675 * the table must store more than 3*256 values because of the possibility
1676 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1677 * values are in the following intervals :
1678 * -176 to 255+176 for red
1679 * -133 to 255+133 for green
1680 * -222 to 255+222 for blue
1682 * If the input y,u,v values are right, the r,g,b results are not expected
1683 * to move out of the 0 to 255 interval but who knows what will happen in
1686 * the red, green and blue conversion tables are stored in a single 1935-entry
1687 * array. The respective positions of each component in the array have been
1688 * calculated to minimize the cache interactions of the 3 tables.
1693 static void yuvToRgb24 (unsigned char * Y,
1694 unsigned char * U, unsigned char * V,
1695 char * dest, int table[1935], int width)
1710 uvRed = (V_RED_COEF*v) >> SHIFT;
1711 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1712 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1714 tableY = table + *(Y++);
1715 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1716 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1718 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1720 *(dest++) = tmp24 >> 8;
1721 *(dest++) = tmp24 >> 16;
1723 tableY = table + *(Y++);
1724 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1725 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1727 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1729 *(dest++) = tmp24 >> 8;
1730 *(dest++) = tmp24 >> 16;
1734 uvRed = (V_RED_COEF*v) >> SHIFT;
1735 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1736 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1738 tableY = table + *(Y++);
1739 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1740 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1742 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1744 *(dest++) = tmp24 >> 8;
1745 *(dest++) = tmp24 >> 16;
1747 tableY = table + *(Y++);
1748 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1749 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1751 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1753 *(dest++) = tmp24 >> 8;
1754 *(dest++) = tmp24 >> 16;
1758 uvRed = (V_RED_COEF*v) >> SHIFT;
1759 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1760 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1762 tableY = table + *(Y++);
1763 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1764 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1766 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1768 *(dest++) = tmp24 >> 8;
1769 *(dest++) = tmp24 >> 16;
1771 tableY = table + *(Y++);
1772 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1773 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1775 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1777 *(dest++) = tmp24 >> 8;
1778 *(dest++) = tmp24 >> 16;
1782 uvRed = (V_RED_COEF*v) >> SHIFT;
1783 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1784 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1786 tableY = table + *(Y++);
1787 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1788 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1790 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1792 *(dest++) = tmp24 >> 8;
1793 *(dest++) = tmp24 >> 16;
1795 tableY = table + *(Y++);
1796 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1797 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1799 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1801 *(dest++) = tmp24 >> 8;
1802 *(dest++) = tmp24 >> 16;
1805 i = (width & 7) >> 1;
1809 uvRed = (V_RED_COEF*v) >> SHIFT;
1810 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1811 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1813 tableY = table + *(Y++);
1814 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1815 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1817 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1819 *(dest++) = tmp24 >> 8;
1820 *(dest++) = tmp24 >> 16;
1822 tableY = table + *(Y++);
1823 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1824 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1826 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1828 *(dest++) = tmp24 >> 8;
1829 *(dest++) = tmp24 >> 16;
1835 uvRed = (V_RED_COEF*v) >> SHIFT;
1836 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1837 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1839 tableY = table + *(Y++);
1840 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1841 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1843 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1845 *(dest++) = tmp24 >> 8;
1846 *(dest++) = tmp24 >> 16;