1 /*******************************************************************************
2 * video_yuv.c: YUV transformation functions
4 *******************************************************************************
5 * Provides functions to perform the YUV conversion. The functions provided here
6 * are a complete and portable C implementation, and may be replaced in certain
7 * case by optimized functions.
8 *******************************************************************************/
10 /*******************************************************************************
12 *******************************************************************************/
21 #include "vlc_thread.h"
23 #include "video_output.h"
24 #include "video_yuv.h"
27 /*******************************************************************************
29 *******************************************************************************/
31 /* Color masks for different color depths - 8bpp masks can be choosen, since
32 * colormaps instead of hardware-defined colors are used. */
34 #define RED_8BPP_MASK 0xe0
35 #define GREEN_8BPP_MASK 0x1c
36 #define BLUE_8BPP_MASK 0x03
38 #define RED_15BPP_MASK 0xf800
39 #define GREEN_15BPP_MASK 0x03e0
40 #define BLUE_15BPP_MASK 0x001f
42 #define RED_16BPP_MASK 0xf800
43 #define GREEN_16BPP_MASK 0x07e0
44 #define BLUE_16BPP_MASK 0x001f
46 #define RED_24BPP_MASK 0xff0000
47 #define GREEN_24BPP_MASK 0x00ff00
48 #define BLUE_24BPP_MASK 0x0000ff
50 /* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
52 const int MATRIX_COEFFICIENTS_TABLE[8][4] =
54 {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
55 {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
56 {104597, 132201, 25675, 53279}, /* unspecified */
57 {104597, 132201, 25675, 53279}, /* reserved */
58 {104448, 132798, 24759, 53109}, /* FCC */
59 {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
60 {104597, 132201, 25675, 53279}, /* SMPTE 170M */
61 {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
64 /* Margins and offsets in conversion tables - Margins are used in case a RGB
65 * RGB conversion would give a value outside the 0-255 range. Offsets have been
66 * calculated to avoid using the same cache line for 2 tables. conversion tables
67 * are 2*MARGIN + 256 long and stores pixels.*/
68 #define RED_MARGIN 178
69 #define GREEN_MARGIN 135
70 #define BLUE_MARGIN 224
71 #define RED_OFFSET 1501 /* 1323 to 1935 */
72 #define GREEN_OFFSET 135 /* 0 to 526 */
73 #define BLUE_OFFSET 818 /* 594 to 1298 */
74 #define RGB_TABLE_SIZE 1935 /* total table size */
76 #define GRAY_MARGIN 384
77 #define GRAY_TABLE_SIZE 1024 /* total table size */
81 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
82 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
83 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
84 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
86 /*******************************************************************************
88 *******************************************************************************/
89 static void SetGammaTable ( int *pi_table, double f_gamma );
90 static void SetYUV ( vout_thread_t *p_vout );
91 static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height,
92 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
94 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,
95 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
96 int i_matrix_coefficients );
97 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,
98 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
99 int i_matrix_coefficients );
100 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,
101 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
102 int i_matrix_coefficients );
103 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,
104 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
105 int i_matrix_coefficients );
106 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,
107 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
108 int i_matrix_coefficients );
109 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,
110 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
111 int i_matrix_coefficients );
112 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,
113 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
114 int i_matrix_coefficients );
115 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,
116 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
117 int i_matrix_coefficients );
118 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,
119 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
120 int i_matrix_coefficients );
121 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,
122 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
123 int i_matrix_coefficients );
124 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,
125 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
126 int i_matrix_coefficients );
127 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,
128 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
129 int i_matrix_coefficients );
130 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,
131 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
132 int i_matrix_coefficients );
133 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,
134 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
135 int i_matrix_coefficients );
136 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,
137 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
138 int i_matrix_coefficients );
139 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,
140 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
141 int i_matrix_coefficients );
143 /*****************************************************************************
144 * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel conversion blocks
145 *****************************************************************************
146 * These conversion routines are used by YUV conversion functions.
147 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
148 * which is also modified.
149 *****************************************************************************/
150 #define CONVERT_Y_PIXEL( BPP ) \
151 /* Only Y sample is present */ \
152 p_ybase = p_yuv + *p_y++; \
153 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
154 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
155 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
157 #define CONVERT_YUV_PIXEL( BPP ) \
158 /* Y, U and V samples are present */ \
161 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
162 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
163 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
164 CONVERT_Y_PIXEL( BPP ) \
166 /*****************************************************************************
167 * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp
168 *****************************************************************************
169 * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
170 *****************************************************************************/
171 #define CONVERT_4YUV_PIXELS( CHROMA ) \
172 *p_pic++ = p_vout->lookup[ \
173 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
174 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
175 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
176 *p_pic++ = p_vout->lookup[ \
177 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
178 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
179 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
180 *p_pic++ = p_vout->lookup[ \
181 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
182 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
183 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
184 *p_pic++ = p_vout->lookup[ \
185 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
186 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
187 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
189 #define CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
190 *p_pic++ = p_vout->lookup[ \
191 (((*p_y + dither10[i_real_y]) >> 4) << 7) \
192 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
193 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
194 i_jump_uv = (i_jump_uv + *p_offset) & 0x1; \
196 p_u += *p_offset & i_jump_uv; \
197 p_v += *p_offset++ & i_jump_uv; \
198 *p_pic++ = p_vout->lookup[ \
199 (((*p_y + dither11[i_real_y]) >> 4) << 7) \
200 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
201 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
202 i_jump_uv = (i_jump_uv + *p_offset) & 0x1; \
204 p_u += *p_offset & i_jump_uv; \
205 p_v += *p_offset++ & i_jump_uv; \
206 *p_pic++ = p_vout->lookup[ \
207 (((*p_y + dither12[i_real_y]) >> 4) << 7) \
208 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
209 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
210 i_jump_uv = (i_jump_uv + *p_offset) & 0x1; \
212 p_u += *p_offset & i_jump_uv; \
213 p_v += *p_offset++ & i_jump_uv; \
214 *p_pic++ = p_vout->lookup[ \
215 (((*p_y + dither13[i_real_y]) >> 4) << 7) \
216 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
217 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
218 i_jump_uv = (i_jump_uv + *p_offset) & 0x1; \
220 p_u += *p_offset & i_jump_uv; \
221 p_v += *p_offset++ & i_jump_uv; \
223 /*****************************************************************************
224 * SCALE_WIDTH: scale a line horizontally
225 *****************************************************************************
226 * This macro scales a line using rendering buffer and offset array. It works
227 * for 1, 2 and 4 Bpp.
228 *****************************************************************************/
229 #define SCALE_WIDTH \
230 if( b_horizontal_scaling ) \
232 /* Horizontal scaling, conversion has been done to buffer. \
233 * Rewind buffer and offset, then copy and scale line */ \
234 p_buffer = p_buffer_start; \
235 p_offset = p_offset_start; \
236 for( i_x = i_pic_width / 16; i_x--; ) \
238 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
239 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
240 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
241 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
242 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
243 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
244 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
245 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
246 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
247 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
248 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
249 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
250 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
251 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
252 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
253 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
255 p_pic += i_pic_line_width; \
259 /* No scaling, conversion has been done directly in picture memory. \
260 * Increment of picture pointer to end of line is still needed */ \
261 p_pic += i_pic_width + i_pic_line_width; \
265 /*****************************************************************************
266 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
267 *****************************************************************************
268 * This macro scales a line using an offset array.
269 *****************************************************************************/
270 #define SCALE_WIDTH_DITHER( CHROMA ) \
271 if( b_horizontal_scaling ) \
273 /* Horizontal scaling, but we can't use a buffer due to dither */ \
274 p_offset = p_offset_start; \
276 for( i_x = i_pic_width / 16; i_x--; ) \
278 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
279 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
280 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
281 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
286 for( i_x = i_width / 16; i_x--; ) \
288 CONVERT_4YUV_PIXELS( CHROMA ) \
289 CONVERT_4YUV_PIXELS( CHROMA ) \
290 CONVERT_4YUV_PIXELS( CHROMA ) \
291 CONVERT_4YUV_PIXELS( CHROMA ) \
294 /* Increment of picture pointer to end of line is still needed */ \
295 p_pic += i_pic_line_width; \
296 i_real_y = (i_real_y + 1) & 0x3; \
298 /*****************************************************************************
299 * SCALE_HEIGHT: handle vertical scaling
300 *****************************************************************************
301 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
302 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
304 *****************************************************************************/
305 #define SCALE_HEIGHT( CHROMA, BPP ) \
306 /* If line is odd, rewind 4:2:0 U and V samples */ \
307 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
309 p_u -= i_chroma_width; \
310 p_v -= i_chroma_width; \
314 * Handle vertical scaling. The current line can be copied or next one \
317 switch( i_vertical_scaling ) \
319 case -1: /* vertical scaling factor is < 1 */ \
320 while( (i_scale_count -= i_pic_height) >= 0 ) \
322 /* Height reduction: skip next source line */ \
325 if( (CHROMA == 420) || (CHROMA == 422) ) \
329 p_u += i_chroma_width; \
330 p_v += i_chroma_width; \
333 else if( CHROMA == 444 ) \
339 i_scale_count += i_height; \
341 case 1: /* vertical scaling factor is > 1 */ \
342 while( (i_scale_count -= i_height) > 0 ) \
344 /* Height increment: copy previous picture line */ \
345 for( i_x = i_pic_width / 16; i_x--; ) \
347 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
348 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
349 if( BPP > 1 ) /* 2, 3, 4 Bpp */ \
351 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
352 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
354 if( BPP > 2 ) /* 3, 4 Bpp */ \
356 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
357 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
359 if( BPP > 3 ) /* 4 Bpp */ \
361 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
362 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
365 p_pic += i_pic_line_width; \
366 p_pic_start += i_pic_line_width; \
368 i_scale_count += i_pic_height; \
372 /*****************************************************************************
373 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
374 *****************************************************************************
375 * This macro handles vertical scaling for a picture. CHROMA may be 420, 422 or
376 * 444 for RGB conversion, or 400 for gray conversion.
377 *****************************************************************************/
378 #define SCALE_HEIGHT_DITHER( CHROMA ) \
380 /* If line is odd, rewind 4:2:0 U and V samples */ \
381 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
383 p_u -= i_chroma_width; \
384 p_v -= i_chroma_width; \
388 * Handle vertical scaling. The current line can be copied or next one \
392 switch( i_vertical_scaling ) \
394 case -1: /* vertical scaling factor is < 1 */ \
395 while( (i_scale_count -= i_pic_height) >= 0 ) \
397 /* Height reduction: skip next source line */ \
400 if( (CHROMA == 420) || (CHROMA == 422) ) \
404 p_u += i_chroma_width; \
405 p_v += i_chroma_width; \
408 else if( CHROMA == 444 ) \
414 i_scale_count += i_height; \
416 case 1: /* vertical scaling factor is > 1 */ \
417 while( (i_scale_count -= i_height) > 0 ) \
419 SCALE_WIDTH_DITHER( CHROMA ); \
421 p_u -= i_chroma_width; \
422 p_v -= i_chroma_width; \
423 p_pic += i_pic_line_width; \
425 i_scale_count += i_pic_height; \
429 /*****************************************************************************
430 * vout_InitYUV: allocate and initialize translations tables
431 *****************************************************************************
432 * This function will allocate memory to store translation tables, depending
433 * of the screen depth.
434 *****************************************************************************/
435 int vout_InitYUV( vout_thread_t *p_vout )
437 size_t tables_size; /* tables size, in bytes */
439 /* Computes tables size - 3 Bpp use 32 bits pixel entries in tables */
440 switch( p_vout->i_bytes_per_pixel )
443 /* nothing to allocate - will put the palette here afterwards */
447 tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
452 tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
456 /* Allocate memory */
457 p_vout->yuv.p_base = malloc( tables_size );
458 if( p_vout->yuv.p_base == NULL )
460 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
464 /* Allocate memory for conversion buffer and offset array */
465 p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
466 if( p_vout->yuv.p_buffer == NULL )
468 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
469 free( p_vout->yuv.p_base );
472 p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );
473 if( p_vout->yuv.p_offset == NULL )
475 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
476 free( p_vout->yuv.p_base );
477 free( p_vout->yuv.p_buffer );
481 /* Initialize tables */
486 /*****************************************************************************
487 * vout_ResetTables: re-initialize translations tables
488 *****************************************************************************
489 * This function will initialize the tables allocated by vout_CreateTables and
490 * set functions pointers.
491 *****************************************************************************/
492 int vout_ResetYUV( vout_thread_t *p_vout )
494 vout_EndYUV( p_vout );
495 return( vout_InitYUV( p_vout ) );
498 /*****************************************************************************
499 * vout_EndYUV: destroy translations tables
500 *****************************************************************************
501 * Free memory allocated by vout_CreateTables.
502 *****************************************************************************/
503 void vout_EndYUV( vout_thread_t *p_vout )
505 free( p_vout->yuv.p_base );
506 free( p_vout->yuv.p_buffer );
507 free( p_vout->yuv.p_offset );
510 /* following functions are local */
512 /*****************************************************************************
513 * SetGammaTable: return intensity table transformed by gamma curve.
514 *****************************************************************************
515 * pi_table is a table of 256 entries from 0 to 255.
516 *****************************************************************************/
517 static void SetGammaTable( int *pi_table, double f_gamma )
519 int i_y; /* base intensity */
521 /* Use exp(gamma) instead of gamma */
522 f_gamma = exp(f_gamma );
524 /* Build gamma table */
525 for( i_y = 0; i_y < 256; i_y++ )
527 pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
531 /*****************************************************************************
532 * SetYUV: compute tables and set function pointers
533 + *****************************************************************************/
534 static void SetYUV( vout_thread_t *p_vout )
536 int pi_gamma[256]; /* gamma table */
537 int i_index; /* index in tables */
539 /* Build gamma table */
540 SetGammaTable( pi_gamma, p_vout->f_gamma );
543 * Set pointers and build YUV tables
545 if( p_vout->b_grayscale )
547 /* Grayscale: build gray table */
548 switch( p_vout->i_bytes_per_pixel )
553 p_vout->yuv.yuv.p_gray16 = (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
554 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
556 p_vout->yuv.yuv.p_gray16[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
557 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
559 for( i_index = 0; i_index < 256; i_index++)
561 p_vout->yuv.yuv.p_gray16[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
566 p_vout->yuv.yuv.p_gray32 = (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
567 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
569 p_vout->yuv.yuv.p_gray32[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
570 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
572 for( i_index = 0; i_index < 256; i_index++)
574 p_vout->yuv.yuv.p_gray32[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
581 /* Color: build red, green and blue tables */
582 switch( p_vout->i_bytes_per_pixel )
587 p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
588 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
590 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
591 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
593 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
595 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
596 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
598 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
600 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
601 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
603 for( i_index = 0; i_index < 256; i_index++ )
605 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
606 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
607 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
612 p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
613 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
615 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
616 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
618 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
620 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
621 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
623 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
625 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
626 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
628 for( i_index = 0; i_index < 256; i_index++ )
630 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
631 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
632 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
639 * Set functions pointers
641 if( p_vout->b_grayscale )
644 switch( p_vout->i_bytes_per_pixel )
647 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;
648 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;
649 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;
652 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
653 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
654 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
657 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
658 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
659 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
662 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
663 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
664 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
671 switch( p_vout->i_bytes_per_pixel )
674 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
675 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
676 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
679 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB16;
680 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB16;
681 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB16;
684 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB24;
685 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB24;
686 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB24;
689 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB32;
690 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB32;
691 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB32;
697 /*****************************************************************************
698 * SetOffset: build offset array for conversion functions
699 *****************************************************************************
700 * This function will build an offset array used in later conversion functions.
701 * It will also set horizontal and vertical scaling indicators.
702 *****************************************************************************/
703 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
704 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
706 int i_x; /* x position in destination */
707 int i_scale_count; /* modulo counter */
710 * Prepare horizontal offset array
712 if( i_pic_width - i_width > 0 )
714 /* Prepare scaling array for horizontal extension */
716 i_scale_count = i_pic_width;
717 for( i_x = i_width; i_x--; )
719 while( (i_scale_count -= i_width) > 0 )
724 i_scale_count += i_pic_width;
727 else if( i_pic_width - i_width < 0 )
729 /* Prepare scaling array for horizontal reduction */
731 i_scale_count = i_pic_width;
732 for( i_x = i_pic_width; i_x--; )
735 while( (i_scale_count -= i_pic_width) >= 0 )
740 i_scale_count += i_width;
745 /* No horizontal scaling: YUV conversion is done directly to picture */
750 * Set vertical scaling indicator
752 if( i_pic_height - i_height > 0 )
756 else if( i_pic_height - i_height < 0 )
766 /*****************************************************************************
767 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
768 *****************************************************************************/
769 static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
770 yuv_data_t *p_u, yuv_data_t *p_v, int i_width,
771 int i_height, int i_pic_width, int i_pic_height,
772 int i_pic_line_width, int i_matrix_coefficients )
774 boolean_t b_horizontal_scaling; /* horizontal scaling type */
775 int i_vertical_scaling; /* vertical scaling type */
776 int i_x, i_y; /* horizontal and vertical indexes */
777 int i_scale_count; /* scale modulo counter */
778 int i_chroma_width; /* chroma width, not used */
779 u8 * p_gray; /* base conversion table */
780 u8 * p_pic_start; /* beginning of the current line for copy */
781 u8 * p_buffer_start; /* conversion buffer start */
782 u8 * p_buffer; /* conversion buffer pointer */
783 int * p_offset_start; /* offset array start */
784 int * p_offset; /* offset array pointer */
787 * Initialize some values - i_pic_line_width will store the line skip
789 i_pic_line_width -= i_pic_width;
790 p_gray = p_vout->yuv.yuv.p_gray8;
791 p_buffer_start = p_vout->yuv.p_buffer;
792 p_offset_start = p_vout->yuv.p_offset;
793 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
794 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
799 i_scale_count = i_pic_height;
800 for( i_y = 0; i_y < i_height; i_y++ )
802 /* Mark beginnning of line for possible later line copy, and initialize
805 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
807 /* Do YUV conversion to buffer - YUV picture is always formed of 16
808 * pixels wide blocks */
809 for( i_x = i_width / 16; i_x--; )
811 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
812 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
813 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
814 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
815 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
816 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
817 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
818 *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
821 /* Do horizontal and vertical scaling */
823 SCALE_HEIGHT(400, 1);
827 /*****************************************************************************
828 * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
829 *****************************************************************************/
830 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,
831 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
832 int i_matrix_coefficients )
834 boolean_t b_horizontal_scaling; /* horizontal scaling type */
835 int i_vertical_scaling; /* vertical scaling type */
836 int i_x, i_y; /* horizontal and vertical indexes */
837 int i_scale_count; /* scale modulo counter */
838 int i_chroma_width; /* chroma width, not used */
839 u16 * p_gray; /* base conversion table */
840 u16 * p_pic_start; /* beginning of the current line for copy */
841 u16 * p_buffer_start; /* conversion buffer start */
842 u16 * p_buffer; /* conversion buffer pointer */
843 int * p_offset_start; /* offset array start */
844 int * p_offset; /* offset array pointer */
847 * Initialize some values - i_pic_line_width will store the line skip
849 i_pic_line_width -= i_pic_width;
850 p_gray = p_vout->yuv.yuv.p_gray16;
851 p_buffer_start = p_vout->yuv.p_buffer;
852 p_offset_start = p_vout->yuv.p_offset;
853 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
854 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
859 i_scale_count = i_pic_height;
860 for( i_y = 0; i_y < i_height; i_y++ )
862 /* Mark beginnning of line for possible later line copy, and initialize
865 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
867 /* Do YUV conversion to buffer - YUV picture is always formed of 16
868 * pixels wide blocks */
869 for( i_x = i_width / 16; i_x--; )
871 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
872 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
873 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
874 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
875 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
876 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
877 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
878 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
881 /* Do horizontal and vertical scaling */
883 SCALE_HEIGHT(400, 2);
887 /*****************************************************************************
888 * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 3 Bpp
889 *****************************************************************************/
890 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,
891 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
892 int i_matrix_coefficients )
897 /*****************************************************************************
898 * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
899 *****************************************************************************/
900 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,
901 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
902 int i_matrix_coefficients )
904 boolean_t b_horizontal_scaling; /* horizontal scaling type */
905 int i_vertical_scaling; /* vertical scaling type */
906 int i_x, i_y; /* horizontal and vertical indexes */
907 int i_scale_count; /* scale modulo counter */
908 int i_chroma_width; /* chroma width, not used */
909 u32 * p_gray; /* base conversion table */
910 u32 * p_pic_start; /* beginning of the current line for copy */
911 u32 * p_buffer_start; /* conversion buffer start */
912 u32 * p_buffer; /* conversion buffer pointer */
913 int * p_offset_start; /* offset array start */
914 int * p_offset; /* offset array pointer */
917 * Initialize some values - i_pic_line_width will store the line skip
919 i_pic_line_width -= i_pic_width;
920 p_gray = p_vout->yuv.yuv.p_gray32;
921 p_buffer_start = p_vout->yuv.p_buffer;
922 p_offset_start = p_vout->yuv.p_offset;
923 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
924 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
929 i_scale_count = i_pic_height;
930 for( i_y = 0; i_y < i_height; i_y++ )
932 /* Mark beginnning of line for possible later line copy, and initialize
935 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
937 /* Do YUV conversion to buffer - YUV picture is always formed of 16
938 * pixels wide blocks */
939 for( i_x = i_width / 16; i_x--; )
941 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
942 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
943 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
944 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
945 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
946 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
947 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
948 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
951 /* Do horizontal and vertical scaling */
953 SCALE_HEIGHT(400, 4);
957 /*****************************************************************************
958 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
959 *****************************************************************************/
960 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,
961 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
962 int i_matrix_coefficients )
964 boolean_t b_horizontal_scaling; /* horizontal scaling type */
965 int i_vertical_scaling; /* vertical scaling type */
966 int i_x, i_y; /* horizontal and vertical indexes */
967 int i_scale_count; /* scale modulo counter */
970 int i_chroma_width; /* chroma width */
971 int * p_offset_start; /* offset array start */
972 int * p_offset; /* offset array pointer */
974 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
975 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
976 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
977 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
978 int dither20[4] = { 0x00, 0x10, 0x04, 0x14 };
979 int dither21[4] = { 0x18, 0x08, 0x1c, 0x0c };
980 int dither22[4] = { 0x06, 0x16, 0x02, 0x12 };
981 int dither23[4] = { 0x1e, 0x0e, 0x1a, 0x0a };
983 //int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
984 //int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
985 //int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
986 //int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
987 //int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
988 //int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
990 * Initialize some values - i_pic_line_width will store the line skip
992 i_pic_line_width -= i_pic_width;
993 i_chroma_width = i_width / 2;
994 p_offset_start = p_vout->yuv.p_offset;
995 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
996 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1001 i_scale_count = i_pic_height;
1003 for( i_y = 0; i_y < i_height; i_y++ )
1005 /* Do horizontal and vertical scaling */
1006 SCALE_WIDTH_DITHER( 420 );
1007 SCALE_HEIGHT_DITHER( 420 );
1011 /*****************************************************************************
1012 * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1013 *****************************************************************************/
1014 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,
1015 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1016 int i_matrix_coefficients )
1018 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1019 int i_vertical_scaling; /* vertical scaling type */
1020 int i_x, i_y; /* horizontal and vertical indexes */
1021 int i_scale_count; /* scale modulo counter */
1022 int i_uval, i_vval; /* U and V samples */
1023 int i_red, i_green, i_blue; /* U and V modified samples */
1024 int i_chroma_width; /* chroma width */
1025 u8 * p_yuv; /* base conversion table */
1026 u8 * p_ybase; /* Y dependant conversion table */
1027 u8 * p_pic_start; /* beginning of the current line for copy */
1028 u8 * p_buffer_start; /* conversion buffer start */
1029 u8 * p_buffer; /* conversion buffer pointer */
1030 int * p_offset_start; /* offset array start */
1031 int * p_offset; /* offset array pointer */
1034 * Initialize some values - i_pic_line_width will store the line skip
1036 i_pic_line_width -= i_pic_width;
1037 i_chroma_width = i_width / 2;
1038 p_yuv = p_vout->yuv.yuv.p_rgb8;
1039 p_buffer_start = p_vout->yuv.p_buffer;
1040 p_offset_start = p_vout->yuv.p_offset;
1041 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1042 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1045 * Perform conversion
1047 i_scale_count = i_pic_height;
1048 for( i_y = 0; i_y < i_height; i_y++ )
1050 /* Mark beginnning of line for possible later line copy, and initialize
1052 p_pic_start = p_pic;
1053 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1055 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1056 * pixels wide blocks */
1057 for( i_x = i_width / 16; i_x--; )
1059 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1060 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1061 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1062 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1063 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1064 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1065 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1066 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1069 /* Do horizontal and vertical scaling */
1071 SCALE_HEIGHT(422, 1);
1075 /*****************************************************************************
1076 * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1077 *****************************************************************************/
1078 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,
1079 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1080 int i_matrix_coefficients )
1082 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1083 int i_vertical_scaling; /* vertical scaling type */
1084 int i_x, i_y; /* horizontal and vertical indexes */
1085 int i_scale_count; /* scale modulo counter */
1086 int i_uval, i_vval; /* U and V samples */
1087 int i_red, i_green, i_blue; /* U and V modified samples */
1088 int i_chroma_width; /* chroma width, not used */
1089 u8 * p_yuv; /* base conversion table */
1090 u8 * p_ybase; /* Y dependant conversion table */
1091 u8 * p_pic_start; /* beginning of the current line for copy */
1092 u8 * p_buffer_start; /* conversion buffer start */
1093 u8 * p_buffer; /* conversion buffer pointer */
1094 int * p_offset_start; /* offset array start */
1095 int * p_offset; /* offset array pointer */
1098 * Initialize some values - i_pic_line_width will store the line skip
1100 i_pic_line_width -= i_pic_width;
1101 p_yuv = p_vout->yuv.yuv.p_rgb8;
1102 p_buffer_start = p_vout->yuv.p_buffer;
1103 p_offset_start = p_vout->yuv.p_offset;
1104 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1105 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1108 * Perform conversion
1110 i_scale_count = i_pic_height;
1111 for( i_y = 0; i_y < i_height; i_y++ )
1113 /* Mark beginnning of line for possible later line copy, and initialize
1115 p_pic_start = p_pic;
1116 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1118 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1119 * pixels wide blocks */
1120 for( i_x = i_width / 16; i_x--; )
1122 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1123 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1124 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1125 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1126 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1127 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1128 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1129 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1132 /* Do horizontal and vertical scaling */
1134 SCALE_HEIGHT(444, 1);
1138 /*****************************************************************************
1139 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1140 *****************************************************************************/
1141 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,
1142 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1143 int i_matrix_coefficients )
1146 // int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
1148 i_chroma_width = i_width / 2;
1149 i_chroma_skip = i_skip / 2;
1150 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1151 (i_width + i_skip) * sizeof( yuv_data_t ),
1152 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1153 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1154 p_vout->i_screen_depth == 15 );
1156 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1157 int i_vertical_scaling; /* vertical scaling type */
1158 int i_x, i_y; /* horizontal and vertical indexes */
1159 int i_scale_count; /* scale modulo counter */
1160 int i_uval, i_vval; /* U and V samples */
1161 int i_red, i_green, i_blue; /* U and V modified samples */
1162 int i_chroma_width; /* chroma width */
1163 u16 * p_yuv; /* base conversion table */
1164 u16 * p_ybase; /* Y dependant conversion table */
1165 u16 * p_pic_start; /* beginning of the current line for copy */
1166 u16 * p_buffer_start; /* conversion buffer start */
1167 u16 * p_buffer; /* conversion buffer pointer */
1168 int * p_offset_start; /* offset array start */
1169 int * p_offset; /* offset array pointer */
1172 * Initialize some values - i_pic_line_width will store the line skip
1174 i_pic_line_width -= i_pic_width;
1175 i_chroma_width = i_width / 2;
1176 p_yuv = p_vout->yuv.yuv.p_rgb16;
1177 p_buffer_start = p_vout->yuv.p_buffer;
1178 p_offset_start = p_vout->yuv.p_offset;
1179 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1180 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1183 * Perform conversion
1185 i_scale_count = i_pic_height;
1186 for( i_y = 0; i_y < i_height; i_y++ )
1188 /* Mark beginnning of line for possible later line copy, and initialize
1190 p_pic_start = p_pic;
1191 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1193 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1194 * pixels wide blocks */
1195 for( i_x = i_width / 16; i_x--; )
1197 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1198 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1199 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1200 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1201 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1202 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1203 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1204 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1207 /* Do horizontal and vertical scaling */
1209 SCALE_HEIGHT(420, 2);
1213 /*****************************************************************************
1214 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1215 *****************************************************************************/
1216 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,
1217 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1218 int i_matrix_coefficients )
1220 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1221 int i_vertical_scaling; /* vertical scaling type */
1222 int i_x, i_y; /* horizontal and vertical indexes */
1223 int i_scale_count; /* scale modulo counter */
1224 int i_uval, i_vval; /* U and V samples */
1225 int i_red, i_green, i_blue; /* U and V modified samples */
1226 int i_chroma_width; /* chroma width */
1227 u16 * p_yuv; /* base conversion table */
1228 u16 * p_ybase; /* Y dependant conversion table */
1229 u16 * p_pic_start; /* beginning of the current line for copy */
1230 u16 * p_buffer_start; /* conversion buffer start */
1231 u16 * p_buffer; /* conversion buffer pointer */
1232 int * p_offset_start; /* offset array start */
1233 int * p_offset; /* offset array pointer */
1236 * Initialize some values - i_pic_line_width will store the line skip
1238 i_pic_line_width -= i_pic_width;
1239 i_chroma_width = i_width / 2;
1240 p_yuv = p_vout->yuv.yuv.p_rgb16;
1241 p_buffer_start = p_vout->yuv.p_buffer;
1242 p_offset_start = p_vout->yuv.p_offset;
1243 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1244 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1247 * Perform conversion
1249 i_scale_count = i_pic_height;
1250 for( i_y = 0; i_y < i_height; i_y++ )
1252 /* Mark beginnning of line for possible later line copy, and initialize
1254 p_pic_start = p_pic;
1255 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1257 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1258 * pixels wide blocks */
1259 for( i_x = i_width / 16; i_x--; )
1261 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1262 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1263 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1264 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1265 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1266 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1267 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1268 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1271 /* Do horizontal and vertical scaling */
1273 SCALE_HEIGHT(422, 2);
1277 /*****************************************************************************
1278 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1279 *****************************************************************************/
1280 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,
1281 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1282 int i_matrix_coefficients )
1284 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1285 int i_vertical_scaling; /* vertical scaling type */
1286 int i_x, i_y; /* horizontal and vertical indexes */
1287 int i_scale_count; /* scale modulo counter */
1288 int i_uval, i_vval; /* U and V samples */
1289 int i_red, i_green, i_blue; /* U and V modified samples */
1290 int i_chroma_width; /* chroma width, not used */
1291 u16 * p_yuv; /* base conversion table */
1292 u16 * p_ybase; /* Y dependant conversion table */
1293 u16 * p_pic_start; /* beginning of the current line for copy */
1294 u16 * p_buffer_start; /* conversion buffer start */
1295 u16 * p_buffer; /* conversion buffer pointer */
1296 int * p_offset_start; /* offset array start */
1297 int * p_offset; /* offset array pointer */
1300 * Initialize some values - i_pic_line_width will store the line skip
1302 i_pic_line_width -= i_pic_width;
1303 p_yuv = p_vout->yuv.yuv.p_rgb16;
1304 p_buffer_start = p_vout->yuv.p_buffer;
1305 p_offset_start = p_vout->yuv.p_offset;
1306 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1307 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1310 * Perform conversion
1312 i_scale_count = i_pic_height;
1313 for( i_y = 0; i_y < i_height; i_y++ )
1315 /* Mark beginnning of line for possible later line copy, and initialize
1317 p_pic_start = p_pic;
1318 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1320 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1321 * pixels wide blocks */
1322 for( i_x = i_width / 16; i_x--; )
1324 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1325 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1326 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1327 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1328 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1329 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1330 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1331 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1334 /* Do horizontal and vertical scaling */
1336 SCALE_HEIGHT(444, 2);
1340 /*****************************************************************************
1341 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1342 *****************************************************************************/
1343 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,
1344 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1345 int i_matrix_coefficients )
1350 /*****************************************************************************
1351 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1352 *****************************************************************************/
1353 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,
1354 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1355 int i_matrix_coefficients )
1360 /*****************************************************************************
1361 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1362 *****************************************************************************/
1363 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,
1364 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1365 int i_matrix_coefficients )
1370 /*****************************************************************************
1371 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1372 *****************************************************************************/
1373 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,
1374 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1375 int i_matrix_coefficients )
1377 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1378 int i_vertical_scaling; /* vertical scaling type */
1379 int i_x, i_y; /* horizontal and vertical indexes */
1380 int i_scale_count; /* scale modulo counter */
1381 int i_uval, i_vval; /* U and V samples */
1382 int i_red, i_green, i_blue; /* U and V modified samples */
1383 int i_chroma_width; /* chroma width */
1384 u32 * p_yuv; /* base conversion table */
1385 u32 * p_ybase; /* Y dependant conversion table */
1386 u32 * p_pic_start; /* beginning of the current line for copy */
1387 u32 * p_buffer_start; /* conversion buffer start */
1388 u32 * p_buffer; /* conversion buffer pointer */
1389 int * p_offset_start; /* offset array start */
1390 int * p_offset; /* offset array pointer */
1393 * Initialize some values - i_pic_line_width will store the line skip
1395 i_pic_line_width -= i_pic_width;
1396 i_chroma_width = i_width / 2;
1397 p_yuv = p_vout->yuv.yuv.p_rgb32;
1398 p_buffer_start = p_vout->yuv.p_buffer;
1399 p_offset_start = p_vout->yuv.p_offset;
1400 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1401 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1404 * Perform conversion
1406 i_scale_count = i_pic_height;
1407 for( i_y = 0; i_y < i_height; i_y++ )
1409 /* Mark beginnning of line for possible later line copy, and initialize
1411 p_pic_start = p_pic;
1412 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1414 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1415 * pixels wide blocks */
1416 for( i_x = i_width / 16; i_x--; )
1418 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1419 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1420 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1421 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1422 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1423 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1424 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1425 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1428 /* Do horizontal and vertical scaling */
1430 SCALE_HEIGHT(420, 4);
1434 /*****************************************************************************
1435 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1436 *****************************************************************************/
1437 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,
1438 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1439 int i_matrix_coefficients )
1441 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1442 int i_vertical_scaling; /* vertical scaling type */
1443 int i_x, i_y; /* horizontal and vertical indexes */
1444 int i_scale_count; /* scale modulo counter */
1445 int i_uval, i_vval; /* U and V samples */
1446 int i_red, i_green, i_blue; /* U and V modified samples */
1447 int i_chroma_width; /* chroma width */
1448 u32 * p_yuv; /* base conversion table */
1449 u32 * p_ybase; /* Y dependant conversion table */
1450 u32 * p_pic_start; /* beginning of the current line for copy */
1451 u32 * p_buffer_start; /* conversion buffer start */
1452 u32 * p_buffer; /* conversion buffer pointer */
1453 int * p_offset_start; /* offset array start */
1454 int * p_offset; /* offset array pointer */
1457 * Initialize some values - i_pic_line_width will store the line skip
1459 i_pic_line_width -= i_pic_width;
1460 i_chroma_width = i_width / 2;
1461 p_yuv = p_vout->yuv.yuv.p_rgb32;
1462 p_buffer_start = p_vout->yuv.p_buffer;
1463 p_offset_start = p_vout->yuv.p_offset;
1464 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1465 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1468 * Perform conversion
1470 i_scale_count = i_pic_height;
1471 for( i_y = 0; i_y < i_height; i_y++ )
1473 /* Mark beginnning of line for possible later line copy, and initialize
1475 p_pic_start = p_pic;
1476 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1478 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1479 * pixels wide blocks */
1480 for( i_x = i_width / 16; i_x--; )
1482 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1483 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1484 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1485 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1486 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1487 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1488 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1489 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1492 /* Do horizontal and vertical scaling */
1494 SCALE_HEIGHT(422, 4);
1498 /*****************************************************************************
1499 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1500 *****************************************************************************/
1501 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,
1502 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1503 int i_matrix_coefficients )
1505 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1506 int i_vertical_scaling; /* vertical scaling type */
1507 int i_x, i_y; /* horizontal and vertical indexes */
1508 int i_scale_count; /* scale modulo counter */
1509 int i_uval, i_vval; /* U and V samples */
1510 int i_red, i_green, i_blue; /* U and V modified samples */
1511 int i_chroma_width; /* chroma width, not used */
1512 u32 * p_yuv; /* base conversion table */
1513 u32 * p_ybase; /* Y dependant conversion table */
1514 u32 * p_pic_start; /* beginning of the current line for copy */
1515 u32 * p_buffer_start; /* conversion buffer start */
1516 u32 * p_buffer; /* conversion buffer pointer */
1517 int * p_offset_start; /* offset array start */
1518 int * p_offset; /* offset array pointer */
1521 * Initialize some values - i_pic_line_width will store the line skip
1523 i_pic_line_width -= i_pic_width;
1524 p_yuv = p_vout->yuv.yuv.p_rgb32;
1525 p_buffer_start = p_vout->yuv.p_buffer;
1526 p_offset_start = p_vout->yuv.p_offset;
1527 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1528 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1531 * Perform conversion
1533 i_scale_count = i_pic_height;
1534 for( i_y = 0; i_y < i_height; i_y++ )
1536 /* Mark beginnning of line for possible later line copy, and initialize
1538 p_pic_start = p_pic;
1539 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1541 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1542 * pixels wide blocks */
1543 for( i_x = i_width / 16; i_x--; )
1545 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1546 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1547 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1548 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1549 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1550 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1551 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1552 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1555 /* Do horizontal and vertical scaling */
1557 SCALE_HEIGHT(444, 4);
1561 //-------------------- walken code follows ------------------------------------
1564 * YUV to RGB routines.
1566 * these routines calculate r, g and b values from each pixel's y, u and v.
1567 * these r, g an b values are then passed thru a table lookup to take the
1568 * gamma curve into account and find the corresponding pixel value.
1570 * the table must store more than 3*256 values because of the possibility
1571 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1572 * values are in the following intervals :
1573 * -176 to 255+176 for red
1574 * -133 to 255+133 for green
1575 * -222 to 255+222 for blue
1577 * If the input y,u,v values are right, the r,g,b results are not expected
1578 * to move out of the 0 to 255 interval but who knows what will happen in
1581 * the red, green and blue conversion tables are stored in a single 1935-entry
1582 * array. The respective positions of each component in the array have been
1583 * calculated to minimize the cache interactions of the 3 tables.
1588 static void yuvToRgb24 (unsigned char * Y,
1589 unsigned char * U, unsigned char * V,
1590 char * dest, int table[1935], int width)
1605 uvRed = (V_RED_COEF*v) >> SHIFT;
1606 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1607 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1609 tableY = table + *(Y++);
1610 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1611 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1613 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1615 *(dest++) = tmp24 >> 8;
1616 *(dest++) = tmp24 >> 16;
1618 tableY = table + *(Y++);
1619 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1620 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1622 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1624 *(dest++) = tmp24 >> 8;
1625 *(dest++) = tmp24 >> 16;
1629 uvRed = (V_RED_COEF*v) >> SHIFT;
1630 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1631 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1633 tableY = table + *(Y++);
1634 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1635 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1637 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1639 *(dest++) = tmp24 >> 8;
1640 *(dest++) = tmp24 >> 16;
1642 tableY = table + *(Y++);
1643 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1644 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1646 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1648 *(dest++) = tmp24 >> 8;
1649 *(dest++) = tmp24 >> 16;
1653 uvRed = (V_RED_COEF*v) >> SHIFT;
1654 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1655 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1657 tableY = table + *(Y++);
1658 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1659 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1661 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1663 *(dest++) = tmp24 >> 8;
1664 *(dest++) = tmp24 >> 16;
1666 tableY = table + *(Y++);
1667 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1668 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1670 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1672 *(dest++) = tmp24 >> 8;
1673 *(dest++) = tmp24 >> 16;
1677 uvRed = (V_RED_COEF*v) >> SHIFT;
1678 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1679 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1681 tableY = table + *(Y++);
1682 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1683 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1685 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1687 *(dest++) = tmp24 >> 8;
1688 *(dest++) = tmp24 >> 16;
1690 tableY = table + *(Y++);
1691 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1692 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1694 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1696 *(dest++) = tmp24 >> 8;
1697 *(dest++) = tmp24 >> 16;
1700 i = (width & 7) >> 1;
1704 uvRed = (V_RED_COEF*v) >> SHIFT;
1705 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1706 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1708 tableY = table + *(Y++);
1709 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1710 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1712 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1714 *(dest++) = tmp24 >> 8;
1715 *(dest++) = tmp24 >> 16;
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;
1730 uvRed = (V_RED_COEF*v) >> SHIFT;
1731 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1732 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1734 tableY = table + *(Y++);
1735 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1736 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1738 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1740 *(dest++) = tmp24 >> 8;
1741 *(dest++) = tmp24 >> 16;