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 /* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
33 const int MATRIX_COEFFICIENTS_TABLE[8][4] =
35 {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
36 {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
37 {104597, 132201, 25675, 53279}, /* unspecified */
38 {104597, 132201, 25675, 53279}, /* reserved */
39 {104448, 132798, 24759, 53109}, /* FCC */
40 {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
41 {104597, 132201, 25675, 53279}, /* SMPTE 170M */
42 {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
45 /* Margins and offsets in convertion tables - Margins are used in case a RGB
46 * RGB convertion would give a value outside the 0-255 range. Offsets have been
47 * calculated to avoid using the same cache line for 2 tables. Convertion tables
48 * are 2*MARGIN + 256 long and stores pixels.*/
49 #define RED_MARGIN 178
50 #define GREEN_MARGIN 135
51 #define BLUE_MARGIN 224
52 #define RED_OFFSET 1501 /* 1323 to 1935 */
53 #define GREEN_OFFSET 135 /* 0 to 526 */
54 #define BLUE_OFFSET 818 /* 594 to 1298 */
55 #define RGB_TABLE_SIZE 1935 /* total table size */
57 #define GRAY_MARGIN 384
58 #define GRAY_TABLE_SIZE 1024 /* total table size */
62 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
63 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
64 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
65 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
67 /*******************************************************************************
69 *******************************************************************************/
70 static int BinaryLog ( u32 i );
71 static void MaskToShift ( int *pi_right, int *pi_left, u32 i_mask );
72 static void SetGammaTable ( int *pi_table, double f_gamma );
73 static void SetYUV ( vout_thread_t *p_vout );
74 static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height,
75 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
77 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,
78 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
79 int i_matrix_coefficients );
80 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,
81 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
82 int i_matrix_coefficients );
83 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,
84 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
85 int i_matrix_coefficients );
86 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,
87 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
88 int i_matrix_coefficients );
89 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,
90 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
91 int i_matrix_coefficients );
92 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,
93 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
94 int i_matrix_coefficients );
95 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,
96 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
97 int i_matrix_coefficients );
98 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,
99 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
100 int i_matrix_coefficients );
101 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,
102 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
103 int i_matrix_coefficients );
104 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,
105 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
106 int i_matrix_coefficients );
107 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,
108 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
109 int i_matrix_coefficients );
110 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,
111 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
112 int i_matrix_coefficients );
114 /*******************************************************************************
115 * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel convertion blocks
116 *******************************************************************************
117 * These convertion routines are used by YUV convertion functions.
118 * Convertion are made from p_y, p_u, p_v, which are modified, to p_buffer,
119 * which is also modified.
120 *******************************************************************************/
121 #define CONVERT_Y_PIXEL \
122 /* Only Y sample is present */ \
123 p_ybase = p_yuv + *p_y++; \
124 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
125 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] | \
126 p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue]; \
128 #define CONVERT_YUV_PIXEL \
129 /* Y, U and V samples are present */ \
132 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
133 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
134 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
137 /*******************************************************************************
138 * SCALE_WIDTH: scale a line horizontally
139 *******************************************************************************
140 * This macro scale a line using rendering buffer and offset array.
141 *******************************************************************************/
142 #define SCALE_WIDTH \
143 if( b_horizontal_scaling ) \
145 /* Horizontal scaling, convertion has been done to buffer. \
146 * Rewind buffer and offset, then copy and scale line */ \
147 p_buffer = p_buffer_start; \
148 p_offset = p_offset_start; \
149 for( i_x = i_pic_width / 16; i_x--; ) \
151 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
152 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
153 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
154 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
155 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
156 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
157 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
158 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
159 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
160 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
161 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
162 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
163 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
164 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
165 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
166 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
168 p_pic += i_pic_line_width; \
172 /* No scaling, convertion has been done directly in picture memory. \
173 * Increment of picture pointer to end of line is still needed */ \
174 p_pic += i_pic_width + i_pic_line_width; \
177 /*******************************************************************************
178 * SCALE_HEIGHT: handle vertical scaling
179 *******************************************************************************
180 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
181 * 444 for RGB convertion, or 400 for gray convertion.
182 *******************************************************************************/
183 #define SCALE_HEIGHT( CHROMA ) \
184 /* If line is odd, rewind 4:2:0 U and V samples */ \
185 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
187 p_u -= i_chroma_width; \
188 p_v -= i_chroma_width; \
192 * Handle vertical scaling. The current line can be copied or next one \
195 switch( i_vertical_scaling ) \
197 case -1: /* vertical scaling factor is < 1 */ \
198 while( (i_scale_count -= i_pic_height) >= 0 ) \
200 /* Height reduction: skip next source line */ \
203 if( (CHROMA == 420) || (CHROMA == 422) ) \
207 p_u += i_chroma_width; \
208 p_v += i_chroma_width; \
211 else if( CHROMA == 444 ) \
217 i_scale_count += i_height; \
219 case 1: /* vertical scaling factor is > 1 */ \
220 while( (i_scale_count -= i_height) > 0 ) \
222 /* Height increment: copy previous picture line */ \
223 for( i_x = i_pic_width / 16; i_x--; ) \
225 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
226 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
227 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
228 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
230 p_pic += i_pic_line_width; \
231 p_pic_start += i_pic_line_width; \
233 i_scale_count += i_pic_height; \
237 /*******************************************************************************
238 * vout_InitYUV: allocate and initialize translations tables
239 *******************************************************************************
240 * This function will allocate memory to store translation tables, depending
241 * of the screen depth.
242 *******************************************************************************/
243 int vout_InitYUV( vout_thread_t *p_vout )
245 size_t tables_size; /* tables size, in bytes */
247 /* Computes tables size */
248 switch( p_vout->i_screen_depth )
252 tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
259 tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
263 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
269 /* Allocate memory */
270 p_vout->yuv.p_base = malloc( tables_size );
271 if( p_vout->yuv.p_base == NULL )
273 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
277 /* Allocate memory for convertion buffer and offset array */
278 p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
279 if( p_vout->yuv.p_buffer == NULL )
281 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
282 free( p_vout->yuv.p_base );
285 p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );
286 if( p_vout->yuv.p_offset == NULL )
288 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
289 free( p_vout->yuv.p_base );
290 free( p_vout->yuv.p_buffer );
294 /* Initialize tables */
299 /*******************************************************************************
300 * vout_ResetTables: re-initialize translations tables
301 *******************************************************************************
302 * This function will initialize the tables allocated by vout_CreateTables and
303 * set functions pointers.
304 *******************************************************************************/
305 int vout_ResetYUV( vout_thread_t *p_vout )
307 vout_EndYUV( p_vout );
308 return( vout_InitYUV( p_vout ) );
311 /*******************************************************************************
312 * vout_EndYUV: destroy translations tables
313 *******************************************************************************
314 * Free memory allocated by vout_CreateTables.
315 *******************************************************************************/
316 void vout_EndYUV( vout_thread_t *p_vout )
318 free( p_vout->yuv.p_base );
319 free( p_vout->yuv.p_buffer );
320 free( p_vout->yuv.p_offset );
323 /* following functions are local */
325 /*******************************************************************************
326 * BinaryLog: computes the base 2 log of a binary value
327 *******************************************************************************
328 * This functions is used by MaskToShift during tables initialisation, to
329 * get a bit index from a binary value.
330 *******************************************************************************/
331 static int BinaryLog(u32 i)
356 if (i != ((u32)1 << i_log))
358 intf_ErrMsg("internal error: binary log overflow\n");
364 /*******************************************************************************
365 * MaskToShift: Transform a color mask into right and left shifts
366 *******************************************************************************
367 * This function is used during table initialisation. It can return a value
368 *******************************************************************************/
369 static void MaskToShift (int *pi_right, int *pi_left, u32 i_mask)
371 u32 i_low, i_high; /* lower hand higher bits of the mask */
374 i_low = i_mask & (- i_mask); /* lower bit of the mask */
375 i_high = i_mask + i_low; /* higher bit of the mask */
377 /* Transform bits into an index */
378 i_low = BinaryLog (i_low);
379 i_high = BinaryLog (i_high);
381 /* Update pointers and return */
383 *pi_right = (8 - i_high + i_low);
386 /*******************************************************************************
387 * SetGammaTable: return intensity table transformed by gamma curve.
388 *******************************************************************************
389 * pi_table is a table of 256 entries from 0 to 255.
390 *******************************************************************************/
391 static void SetGammaTable( int *pi_table, double f_gamma )
393 int i_y; /* base intensity */
395 /* Use exp(gamma) instead of gamma */
396 f_gamma = exp(f_gamma );
398 /* Build gamma table */
399 for( i_y = 0; i_y < 256; i_y++ )
401 pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
405 /*******************************************************************************
406 * SetYUV: compute tables and set function pointers
407 + *******************************************************************************/
408 static void SetYUV( vout_thread_t *p_vout )
410 int pi_gamma[256]; /* gamma table */
411 int i_index; /* index in tables */
412 int i_red_right, i_red_left; /* red shifts */
413 int i_green_right, i_green_left; /* green shifts */
414 int i_blue_right, i_blue_left; /* blue shifts */
416 /* Build gamma table */
417 SetGammaTable( pi_gamma, p_vout->f_gamma );
420 * Set color masks and shifts
422 switch( p_vout->i_screen_depth )
425 MaskToShift( &i_red_right, &i_red_left, 0xf800 );
426 MaskToShift( &i_green_right, &i_green_left, 0x03e0 );
427 MaskToShift( &i_blue_right, &i_blue_left, 0x001f );
430 MaskToShift( &i_red_right, &i_red_left, 0xf800 );
431 MaskToShift( &i_green_right, &i_green_left, 0x07e0 );
432 MaskToShift( &i_blue_right, &i_blue_left, 0x001f );
436 MaskToShift( &i_red_right, &i_red_left, 0x00ff0000 );
437 MaskToShift( &i_green_right, &i_green_left, 0x0000ff00 );
438 MaskToShift( &i_blue_right, &i_blue_left, 0x000000ff );
442 intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
448 * Set pointers and build YUV tables
450 if( p_vout->b_grayscale )
452 /* Grayscale: build gray table */
453 switch( p_vout->i_screen_depth )
457 p_vout->yuv.yuv.p_gray16 = (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
458 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
460 p_vout->yuv.yuv.p_gray16[ -i_index ] =
461 ((pi_gamma[ 0 ] >> i_red_right) << i_red_left) |
462 ((pi_gamma[ 0 ] >> i_green_right) << i_green_left) |
463 ((pi_gamma[ 0 ] >> i_blue_right) << i_blue_left);
464 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] =
465 ((pi_gamma[ 255 ] >> i_red_right) << i_red_left) |
466 ((pi_gamma[ 255 ] >> i_green_right) << i_green_left) |
467 ((pi_gamma[ 255 ] >> i_blue_right) << i_blue_left);
469 for( i_index = 0; i_index < 256; i_index++)
471 p_vout->yuv.yuv.p_gray16[ i_index ] =
472 ((pi_gamma[ i_index ] >> i_red_right) << i_red_left) |
473 ((pi_gamma[ i_index ] >> i_green_right) << i_green_left) |
474 ((pi_gamma[ i_index ] >> i_blue_right) << i_blue_left);
479 p_vout->yuv.yuv.p_gray32 = (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
480 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
482 p_vout->yuv.yuv.p_gray32[ -i_index ] =
483 ((pi_gamma[ 0 ] >> i_red_right) << i_red_left) |
484 ((pi_gamma[ 0 ] >> i_green_right) << i_green_left) |
485 ((pi_gamma[ 0 ] >> i_blue_right) << i_blue_left);
486 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] =
487 ((pi_gamma[ 255 ] >> i_red_right) << i_red_left) |
488 ((pi_gamma[ 255 ] >> i_green_right) << i_green_left) |
489 ((pi_gamma[ 255 ] >> i_blue_right) << i_blue_left);
491 for( i_index = 0; i_index < 256; i_index++)
493 p_vout->yuv.yuv.p_gray32[ i_index ] =
494 ((pi_gamma[ i_index ] >> i_red_right) << i_red_left) |
495 ((pi_gamma[ i_index ] >> i_green_right) << i_green_left) |
496 ((pi_gamma[ i_index ] >> i_blue_right) << i_blue_left);
503 /* Color: build red, green and blue tables */
504 switch( p_vout->i_screen_depth )
508 p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
509 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
511 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
512 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;
514 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
516 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right)<<i_green_left;
517 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
519 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
521 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
522 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;
524 for( i_index = 0; i_index < 256; i_index++ )
526 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
527 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
528 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
533 p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
534 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
536 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = (pi_gamma[0]>>i_red_right)<<i_red_left;
537 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_red_right)<<i_red_left;
539 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
541 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = (pi_gamma[0]>>i_green_right)<<i_green_left;
542 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = (pi_gamma[255]>>i_green_right)<<i_green_left;
544 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
546 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = (pi_gamma[0]>>i_blue_right)<<i_blue_left;
547 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = (pi_gamma[255]>>i_blue_right)<<i_blue_left;
549 for( i_index = 0; i_index < 256; i_index++ )
551 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = (pi_gamma[i_index]>>i_red_right)<<i_red_left;
552 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = (pi_gamma[i_index]>>i_green_right)<<i_green_left;
553 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = (pi_gamma[i_index]>>i_blue_right)<<i_blue_left;
560 * Set functions pointers
562 if( p_vout->b_grayscale )
565 switch( p_vout->i_screen_depth )
569 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
570 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
571 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
574 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
575 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
576 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
579 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
580 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
581 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
588 switch( p_vout->i_screen_depth )
592 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB16;
593 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB16;
594 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB16;
597 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB24;
598 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB24;
599 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB24;
602 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB32;
603 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB32;
604 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB32;
610 /*******************************************************************************
611 * SetOffset: build offset array for convertion functions
612 *******************************************************************************
613 * This function will build an offset array used in later convertion functions.
614 * It will also set horizontal and vertical scaling indicators.
615 *******************************************************************************/
616 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
617 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
619 int i_x; /* x position in destination */
620 int i_scale_count; /* modulo counter */
623 * Prepare horizontal offset array
625 if( i_pic_width - i_width > 0 )
627 /* Prepare scaling array for horizontal extension */
629 i_scale_count = i_pic_width;
630 for( i_x = i_width; i_x--; )
632 while( (i_scale_count -= i_width) > 0 )
637 i_scale_count += i_pic_width;
640 else if( i_pic_width - i_width < 0 )
642 /* Prepare scaling array for horizontal reduction */
644 i_scale_count = i_pic_width;
645 for( i_x = i_pic_width; i_x--; )
648 while( (i_scale_count -= i_pic_width) >= 0 )
653 i_scale_count += i_width;
658 /* No horizontal scaling: YUV convertion is done directly to picture */
663 * Set vertical scaling indicator
665 if( i_pic_height - i_height > 0 )
669 else if( i_pic_height - i_height < 0 )
679 /*******************************************************************************
680 * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 15 or 16 bpp
681 *******************************************************************************/
682 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,
683 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
684 int i_matrix_coefficients )
686 boolean_t b_horizontal_scaling; /* horizontal scaling type */
687 int i_vertical_scaling; /* vertical scaling type */
688 int i_x, i_y; /* horizontal and vertical indexes */
689 int i_scale_count; /* scale modulo counter */
690 int i_chroma_width; /* chroma width, not used */
691 u16 * p_gray; /* base convertion table */
692 u16 * p_pic_start; /* beginning of the current line for copy */
693 u16 * p_buffer_start; /* convertion buffer start */
694 u16 * p_buffer; /* convertion buffer pointer */
695 int * p_offset_start; /* offset array start */
696 int * p_offset; /* offset array pointer */
699 * Initialize some values - i_pic_line_width will store the line skip
701 i_pic_line_width -= i_pic_width;
702 p_gray = p_vout->yuv.yuv.p_gray16;
703 p_buffer_start = p_vout->yuv.p_buffer;
704 p_offset_start = p_vout->yuv.p_offset;
705 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
706 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
711 i_scale_count = i_pic_height;
712 for( i_y = 0; i_y < i_height; i_y++ )
714 /* Mark beginnning of line for possible later line copy, and initialize
717 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
719 /* Do YUV convertion to buffer - YUV picture is always formed of 16
720 * pixels wide blocks */
721 for( i_x = i_width / 16; i_x--; )
723 *p_buffer++ = p_gray[ *p_y++ ];
724 *p_buffer++ = p_gray[ *p_y++ ];
725 *p_buffer++ = p_gray[ *p_y++ ];
726 *p_buffer++ = p_gray[ *p_y++ ];
727 *p_buffer++ = p_gray[ *p_y++ ];
728 *p_buffer++ = p_gray[ *p_y++ ];
729 *p_buffer++ = p_gray[ *p_y++ ];
730 *p_buffer++ = p_gray[ *p_y++ ];
731 *p_buffer++ = p_gray[ *p_y++ ];
732 *p_buffer++ = p_gray[ *p_y++ ];
733 *p_buffer++ = p_gray[ *p_y++ ];
734 *p_buffer++ = p_gray[ *p_y++ ];
735 *p_buffer++ = p_gray[ *p_y++ ];
736 *p_buffer++ = p_gray[ *p_y++ ];
737 *p_buffer++ = p_gray[ *p_y++ ];
738 *p_buffer++ = p_gray[ *p_y++ ];
741 /* Do horizontal and vertical scaling */
747 /*******************************************************************************
748 * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 24 bpp
749 *******************************************************************************/
750 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,
751 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
752 int i_matrix_coefficients )
757 /*******************************************************************************
758 * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 32 bpp
759 *******************************************************************************/
760 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,
761 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
762 int i_matrix_coefficients )
764 boolean_t b_horizontal_scaling; /* horizontal scaling type */
765 int i_vertical_scaling; /* vertical scaling type */
766 int i_x, i_y; /* horizontal and vertical indexes */
767 int i_scale_count; /* scale modulo counter */
768 int i_chroma_width; /* chroma width, not used */
769 u32 * p_gray; /* base convertion table */
770 u32 * p_pic_start; /* beginning of the current line for copy */
771 u32 * p_buffer_start; /* convertion buffer start */
772 u32 * p_buffer; /* convertion buffer pointer */
773 int * p_offset_start; /* offset array start */
774 int * p_offset; /* offset array pointer */
777 * Initialize some values - i_pic_line_width will store the line skip
779 i_pic_line_width -= i_pic_width;
780 p_gray = p_vout->yuv.yuv.p_gray32;
781 p_buffer_start = p_vout->yuv.p_buffer;
782 p_offset_start = p_vout->yuv.p_offset;
783 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
784 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
789 i_scale_count = i_pic_height;
790 for( i_y = 0; i_y < i_height; i_y++ )
792 /* Mark beginnning of line for possible later line copy, and initialize
795 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
797 /* Do YUV convertion to buffer - YUV picture is always formed of 16
798 * pixels wide blocks */
799 for( i_x = i_width / 16; i_x--; )
801 *p_buffer++ = p_gray[ *p_y++ ];
802 *p_buffer++ = p_gray[ *p_y++ ];
803 *p_buffer++ = p_gray[ *p_y++ ];
804 *p_buffer++ = p_gray[ *p_y++ ];
805 *p_buffer++ = p_gray[ *p_y++ ];
806 *p_buffer++ = p_gray[ *p_y++ ];
807 *p_buffer++ = p_gray[ *p_y++ ];
808 *p_buffer++ = p_gray[ *p_y++ ];
809 *p_buffer++ = p_gray[ *p_y++ ];
810 *p_buffer++ = p_gray[ *p_y++ ];
811 *p_buffer++ = p_gray[ *p_y++ ];
812 *p_buffer++ = p_gray[ *p_y++ ];
813 *p_buffer++ = p_gray[ *p_y++ ];
814 *p_buffer++ = p_gray[ *p_y++ ];
815 *p_buffer++ = p_gray[ *p_y++ ];
816 *p_buffer++ = p_gray[ *p_y++ ];
819 /* Do horizontal and vertical scaling */
825 /*******************************************************************************
826 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 15 or 16 bpp
827 *******************************************************************************/
828 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,
829 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
830 int i_matrix_coefficients )
833 // int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
835 i_chroma_width = i_width / 2;
836 i_chroma_skip = i_skip / 2;
837 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
838 (i_width + i_skip) * sizeof( yuv_data_t ),
839 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
840 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
841 p_vout->i_screen_depth == 15 );
843 boolean_t b_horizontal_scaling; /* horizontal scaling type */
844 int i_vertical_scaling; /* vertical scaling type */
845 int i_x, i_y; /* horizontal and vertical indexes */
846 int i_scale_count; /* scale modulo counter */
847 int i_uval, i_vval; /* U and V samples */
848 int i_red, i_green, i_blue; /* U and V modified samples */
849 int i_chroma_width; /* chroma width */
850 u16 * p_yuv; /* base convertion table */
851 u16 * p_ybase; /* Y dependant convertion table */
852 u16 * p_pic_start; /* beginning of the current line for copy */
853 u16 * p_buffer_start; /* convertion buffer start */
854 u16 * p_buffer; /* convertion buffer pointer */
855 int * p_offset_start; /* offset array start */
856 int * p_offset; /* offset array pointer */
859 * Initialize some values - i_pic_line_width will store the line skip
861 i_pic_line_width -= i_pic_width;
862 i_chroma_width = i_width / 2;
863 p_yuv = p_vout->yuv.yuv.p_rgb16;
864 p_buffer_start = p_vout->yuv.p_buffer;
865 p_offset_start = p_vout->yuv.p_offset;
866 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
867 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
872 i_scale_count = i_pic_height;
873 for( i_y = 0; i_y < i_height; i_y++ )
875 /* Mark beginnning of line for possible later line copy, and initialize
878 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
880 /* Do YUV convertion to buffer - YUV picture is always formed of 16
881 * pixels wide blocks */
882 for( i_x = i_width / 16; i_x--; )
884 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
885 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
886 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
887 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
888 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
889 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
890 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
891 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
894 /* Do horizontal and vertical scaling */
900 /*******************************************************************************
901 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 15 or 16 bpp
902 *******************************************************************************/
903 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,
904 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
905 int i_matrix_coefficients )
907 boolean_t b_horizontal_scaling; /* horizontal scaling type */
908 int i_vertical_scaling; /* vertical scaling type */
909 int i_x, i_y; /* horizontal and vertical indexes */
910 int i_scale_count; /* scale modulo counter */
911 int i_uval, i_vval; /* U and V samples */
912 int i_red, i_green, i_blue; /* U and V modified samples */
913 int i_chroma_width; /* chroma width */
914 u16 * p_yuv; /* base convertion table */
915 u16 * p_ybase; /* Y dependant convertion table */
916 u16 * p_pic_start; /* beginning of the current line for copy */
917 u16 * p_buffer_start; /* convertion buffer start */
918 u16 * p_buffer; /* convertion buffer pointer */
919 int * p_offset_start; /* offset array start */
920 int * p_offset; /* offset array pointer */
923 * Initialize some values - i_pic_line_width will store the line skip
925 i_pic_line_width -= i_pic_width;
926 i_chroma_width = i_width / 2;
927 p_yuv = p_vout->yuv.yuv.p_rgb16;
928 p_buffer_start = p_vout->yuv.p_buffer;
929 p_offset_start = p_vout->yuv.p_offset;
930 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
931 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
936 i_scale_count = i_pic_height;
937 for( i_y = 0; i_y < i_height; i_y++ )
939 /* Mark beginnning of line for possible later line copy, and initialize
942 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
944 /* Do YUV convertion to buffer - YUV picture is always formed of 16
945 * pixels wide blocks */
946 for( i_x = i_width / 16; i_x--; )
948 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
949 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
950 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
951 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
952 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
953 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
954 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
955 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
958 /* Do horizontal and vertical scaling */
964 /*******************************************************************************
965 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 15 or 16 bpp
966 *******************************************************************************/
967 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,
968 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
969 int i_matrix_coefficients )
971 boolean_t b_horizontal_scaling; /* horizontal scaling type */
972 int i_vertical_scaling; /* vertical scaling type */
973 int i_x, i_y; /* horizontal and vertical indexes */
974 int i_scale_count; /* scale modulo counter */
975 int i_uval, i_vval; /* U and V samples */
976 int i_red, i_green, i_blue; /* U and V modified samples */
977 int i_chroma_width; /* chroma width, not used */
978 u16 * p_yuv; /* base convertion table */
979 u16 * p_ybase; /* Y dependant convertion table */
980 u16 * p_pic_start; /* beginning of the current line for copy */
981 u16 * p_buffer_start; /* convertion buffer start */
982 u16 * p_buffer; /* convertion buffer pointer */
983 int * p_offset_start; /* offset array start */
984 int * p_offset; /* offset array pointer */
987 * Initialize some values - i_pic_line_width will store the line skip
989 i_pic_line_width -= i_pic_width;
990 p_yuv = p_vout->yuv.yuv.p_rgb16;
991 p_buffer_start = p_vout->yuv.p_buffer;
992 p_offset_start = p_vout->yuv.p_offset;
993 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
994 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
999 i_scale_count = i_pic_height;
1000 for( i_y = 0; i_y < i_height; i_y++ )
1002 /* Mark beginnning of line for possible later line copy, and initialize
1004 p_pic_start = p_pic;
1005 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1007 /* Do YUV convertion to buffer - YUV picture is always formed of 16
1008 * pixels wide blocks */
1009 for( i_x = i_width / 16; i_x--; )
1011 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1012 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1013 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1014 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1015 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1016 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1017 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1018 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1021 /* Do horizontal and vertical scaling */
1027 /*******************************************************************************
1028 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 24 bpp
1029 *******************************************************************************/
1030 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,
1031 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1032 int i_matrix_coefficients )
1037 /*******************************************************************************
1038 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 24 bpp
1039 *******************************************************************************/
1040 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,
1041 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1042 int i_matrix_coefficients )
1047 /*******************************************************************************
1048 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 24 bpp
1049 *******************************************************************************/
1050 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,
1051 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1052 int i_matrix_coefficients )
1057 /*******************************************************************************
1058 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 32 bpp
1059 *******************************************************************************/
1060 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,
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 i_uval, i_vval; /* U and V samples */
1069 int i_red, i_green, i_blue; /* U and V modified samples */
1070 int i_chroma_width; /* chroma width */
1071 u32 * p_yuv; /* base convertion table */
1072 u32 * p_ybase; /* Y dependant convertion table */
1073 u32 * p_pic_start; /* beginning of the current line for copy */
1074 u32 * p_buffer_start; /* convertion buffer start */
1075 u32 * p_buffer; /* convertion buffer pointer */
1076 int * p_offset_start; /* offset array start */
1077 int * p_offset; /* offset array pointer */
1080 * Initialize some values - i_pic_line_width will store the line skip
1082 i_pic_line_width -= i_pic_width;
1083 i_chroma_width = i_width / 2;
1084 p_yuv = p_vout->yuv.yuv.p_rgb32;
1085 p_buffer_start = p_vout->yuv.p_buffer;
1086 p_offset_start = p_vout->yuv.p_offset;
1087 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1088 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1091 * Perform convertion
1093 i_scale_count = i_pic_height;
1094 for( i_y = 0; i_y < i_height; i_y++ )
1096 /* Mark beginnning of line for possible later line copy, and initialize
1098 p_pic_start = p_pic;
1099 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1101 /* Do YUV convertion to buffer - YUV picture is always formed of 16
1102 * pixels wide blocks */
1103 for( i_x = i_width / 16; i_x--; )
1105 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1106 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1107 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1108 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1109 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1110 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1111 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1112 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1115 /* Do horizontal and vertical scaling */
1121 /*******************************************************************************
1122 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 32 bpp
1123 *******************************************************************************/
1124 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,
1125 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1126 int i_matrix_coefficients )
1128 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1129 int i_vertical_scaling; /* vertical scaling type */
1130 int i_x, i_y; /* horizontal and vertical indexes */
1131 int i_scale_count; /* scale modulo counter */
1132 int i_uval, i_vval; /* U and V samples */
1133 int i_red, i_green, i_blue; /* U and V modified samples */
1134 int i_chroma_width; /* chroma width */
1135 u32 * p_yuv; /* base convertion table */
1136 u32 * p_ybase; /* Y dependant convertion table */
1137 u32 * p_pic_start; /* beginning of the current line for copy */
1138 u32 * p_buffer_start; /* convertion buffer start */
1139 u32 * p_buffer; /* convertion buffer pointer */
1140 int * p_offset_start; /* offset array start */
1141 int * p_offset; /* offset array pointer */
1144 * Initialize some values - i_pic_line_width will store the line skip
1146 i_pic_line_width -= i_pic_width;
1147 i_chroma_width = i_width / 2;
1148 p_yuv = p_vout->yuv.yuv.p_rgb32;
1149 p_buffer_start = p_vout->yuv.p_buffer;
1150 p_offset_start = p_vout->yuv.p_offset;
1151 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1152 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1155 * Perform convertion
1157 i_scale_count = i_pic_height;
1158 for( i_y = 0; i_y < i_height; i_y++ )
1160 /* Mark beginnning of line for possible later line copy, and initialize
1162 p_pic_start = p_pic;
1163 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1165 /* Do YUV convertion to buffer - YUV picture is always formed of 16
1166 * pixels wide blocks */
1167 for( i_x = i_width / 16; i_x--; )
1169 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1170 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1171 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1172 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1173 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1174 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1175 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1176 CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
1179 /* Do horizontal and vertical scaling */
1185 /*******************************************************************************
1186 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 32 bpp
1187 *******************************************************************************/
1188 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,
1189 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1190 int i_matrix_coefficients )
1192 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1193 int i_vertical_scaling; /* vertical scaling type */
1194 int i_x, i_y; /* horizontal and vertical indexes */
1195 int i_scale_count; /* scale modulo counter */
1196 int i_uval, i_vval; /* U and V samples */
1197 int i_red, i_green, i_blue; /* U and V modified samples */
1198 int i_chroma_width; /* chroma width, not used */
1199 u32 * p_yuv; /* base convertion table */
1200 u32 * p_ybase; /* Y dependant convertion table */
1201 u32 * p_pic_start; /* beginning of the current line for copy */
1202 u32 * p_buffer_start; /* convertion buffer start */
1203 u32 * p_buffer; /* convertion buffer pointer */
1204 int * p_offset_start; /* offset array start */
1205 int * p_offset; /* offset array pointer */
1208 * Initialize some values - i_pic_line_width will store the line skip
1210 i_pic_line_width -= i_pic_width;
1211 p_yuv = p_vout->yuv.yuv.p_rgb32;
1212 p_buffer_start = p_vout->yuv.p_buffer;
1213 p_offset_start = p_vout->yuv.p_offset;
1214 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1215 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1218 * Perform convertion
1220 i_scale_count = i_pic_height;
1221 for( i_y = 0; i_y < i_height; i_y++ )
1223 /* Mark beginnning of line for possible later line copy, and initialize
1225 p_pic_start = p_pic;
1226 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1228 /* Do YUV convertion to buffer - YUV picture is always formed of 16
1229 * pixels wide blocks */
1230 for( i_x = i_width / 16; i_x--; )
1232 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1233 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1234 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1235 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1236 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1237 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1238 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1239 CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
1242 /* Do horizontal and vertical scaling */
1248 //-------------------- walken code follow ---------------------------------------
1251 * YUV to RGB routines.
1253 * these routines calculate r, g and b values from each pixel's y, u and v.
1254 * these r, g an b values are then passed thru a table lookup to take the
1255 * gamma curve into account and find the corresponding pixel value.
1257 * the table must store more than 3*256 values because of the possibility
1258 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1259 * values are in the following intervals :
1260 * -176 to 255+176 for red
1261 * -133 to 255+133 for green
1262 * -222 to 255+222 for blue
1264 * If the input y,u,v values are right, the r,g,b results are not expected
1265 * to move out of the 0 to 255 interval but who knows what will happen in
1268 * the red, green and blue conversion tables are stored in a single 1935-entry
1269 * array. The respective positions of each component in the array have been
1270 * calculated to minimize the cache interactions of the 3 tables.
1273 static void yuvToRgb24 (unsigned char * Y,
1274 unsigned char * U, unsigned char * V,
1275 char * dest, int table[1935], int width)
1290 uvRed = (V_RED_COEF*v) >> SHIFT;
1291 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1292 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1294 tableY = table + *(Y++);
1295 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1296 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1298 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1300 *(dest++) = tmp24 >> 8;
1301 *(dest++) = tmp24 >> 16;
1303 tableY = table + *(Y++);
1304 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1305 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1307 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1309 *(dest++) = tmp24 >> 8;
1310 *(dest++) = tmp24 >> 16;
1314 uvRed = (V_RED_COEF*v) >> SHIFT;
1315 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1316 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1318 tableY = table + *(Y++);
1319 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1320 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1322 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1324 *(dest++) = tmp24 >> 8;
1325 *(dest++) = tmp24 >> 16;
1327 tableY = table + *(Y++);
1328 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1329 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1331 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1333 *(dest++) = tmp24 >> 8;
1334 *(dest++) = tmp24 >> 16;
1338 uvRed = (V_RED_COEF*v) >> SHIFT;
1339 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1340 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1342 tableY = table + *(Y++);
1343 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1344 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1346 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1348 *(dest++) = tmp24 >> 8;
1349 *(dest++) = tmp24 >> 16;
1351 tableY = table + *(Y++);
1352 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1353 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1355 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1357 *(dest++) = tmp24 >> 8;
1358 *(dest++) = tmp24 >> 16;
1362 uvRed = (V_RED_COEF*v) >> SHIFT;
1363 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1364 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1366 tableY = table + *(Y++);
1367 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1368 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1370 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1372 *(dest++) = tmp24 >> 8;
1373 *(dest++) = tmp24 >> 16;
1375 tableY = table + *(Y++);
1376 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1377 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1379 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1381 *(dest++) = tmp24 >> 8;
1382 *(dest++) = tmp24 >> 16;
1385 i = (width & 7) >> 1;
1389 uvRed = (V_RED_COEF*v) >> SHIFT;
1390 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1391 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1393 tableY = table + *(Y++);
1394 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1395 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1397 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1399 *(dest++) = tmp24 >> 8;
1400 *(dest++) = tmp24 >> 16;
1402 tableY = table + *(Y++);
1403 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1404 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1406 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1408 *(dest++) = tmp24 >> 8;
1409 *(dest++) = tmp24 >> 16;
1415 uvRed = (V_RED_COEF*v) >> SHIFT;
1416 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1417 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1419 tableY = table + *(Y++);
1420 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1421 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1423 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1425 *(dest++) = tmp24 >> 8;
1426 *(dest++) = tmp24 >> 16;