1 /*****************************************************************************
2 * video_yuv.c: YUV transformation functions
3 * Provides functions to perform the YUV conversion. The functions provided here
4 * are a complete and portable C implementation, and may be replaced in certain
5 * case by optimized functions.
6 *****************************************************************************
7 * Copyright (C) 1999, 2000 VideoLAN
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public
22 * License along with this program; if not, write to the
23 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 * Boston, MA 02111-1307, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
30 #include <math.h> /* exp(), pow() */
31 #include <errno.h> /* ENOMEM */
32 #include <stdlib.h> /* free() */
33 #include <string.h> /* strerror() */
40 #include "video_output.h"
41 #include "video_yuv.h"
45 /*****************************************************************************
47 *****************************************************************************/
49 /* Margins and offsets in conversion tables - Margins are used in case a RGB
50 * RGB conversion would give a value outside the 0-255 range. Offsets have been
51 * calculated to avoid using the same cache line for 2 tables. conversion tables
52 * are 2*MARGIN + 256 long and stores pixels.*/
53 #define RED_MARGIN 178
54 #define GREEN_MARGIN 135
55 #define BLUE_MARGIN 224
56 #define RED_OFFSET 1501 /* 1323 to 1935 */
57 #define GREEN_OFFSET 135 /* 0 to 526 */
58 #define BLUE_OFFSET 818 /* 594 to 1298 */
59 #define RGB_TABLE_SIZE 1935 /* total table size */
61 #define GRAY_MARGIN 384
62 #define GRAY_TABLE_SIZE 1024 /* total table size */
64 #define PALETTE_TABLE_SIZE 2176 /* YUV -> 8bpp palette lookup table */
66 /* macros used for YUV pixel conversions */
68 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
69 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
70 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
71 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
73 /*****************************************************************************
75 *****************************************************************************/
76 static void SetGammaTable ( int *pi_table, double f_gamma );
77 static void SetYUV ( vout_thread_t *p_vout );
78 static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height,
79 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
81 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,
82 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
83 int i_matrix_coefficients );
84 static void 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,
85 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
86 int i_matrix_coefficients );
87 static void 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,
88 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
89 int i_matrix_coefficients );
90 static void 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,
91 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
92 int i_matrix_coefficients );
93 static void 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,
94 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
95 int i_matrix_coefficients );
96 static void 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,
97 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
98 int i_matrix_coefficients );
99 static void 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,
100 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
101 int i_matrix_coefficients );
102 static void 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,
103 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
104 int i_matrix_coefficients );
105 static void 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,
106 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
107 int i_matrix_coefficients );
108 static void 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,
109 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
110 int i_matrix_coefficients );
111 static void 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,
112 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
113 int i_matrix_coefficients );
114 static void 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,
115 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
116 int i_matrix_coefficients );
117 static void 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,
118 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
119 int i_matrix_coefficients );
120 static void 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,
121 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
122 int i_matrix_coefficients );
123 static void 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,
124 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
125 int i_matrix_coefficients );
126 static void 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,
127 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
128 int i_matrix_coefficients );
130 /*****************************************************************************
131 * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel conversion blocks
132 *****************************************************************************
133 * These conversion routines are used by YUV conversion functions.
134 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
135 * which is also modified.
136 *****************************************************************************/
137 #define CONVERT_Y_PIXEL( BPP ) \
138 /* Only Y sample is present */ \
139 p_ybase = p_yuv + *p_y++; \
140 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
141 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
142 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
144 #define CONVERT_YUV_PIXEL( BPP ) \
145 /* Y, U and V samples are present */ \
148 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
149 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
150 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
151 CONVERT_Y_PIXEL( BPP ) \
153 /*****************************************************************************
154 * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp
155 *****************************************************************************
156 * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
157 *****************************************************************************/
158 #define CONVERT_4YUV_PIXELS( CHROMA ) \
159 *p_pic++ = p_lookup[ \
160 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
161 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
162 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
163 *p_pic++ = p_lookup[ \
164 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
165 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
166 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
167 *p_pic++ = p_lookup[ \
168 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
169 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
170 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
171 *p_pic++ = p_lookup[ \
172 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
173 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
174 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
176 #define CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
177 *p_pic++ = p_lookup[ \
178 (((*p_y + dither10[i_real_y]) >> 4) << 7) \
179 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
180 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
181 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
183 p_u += *p_offset & b_jump_uv; \
184 p_v += *p_offset++ & b_jump_uv; \
185 *p_pic++ = p_lookup[ \
186 (((*p_y + dither11[i_real_y]) >> 4) << 7) \
187 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
188 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
189 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
191 p_u += *p_offset & b_jump_uv; \
192 p_v += *p_offset++ & b_jump_uv; \
193 *p_pic++ = p_lookup[ \
194 (((*p_y + dither12[i_real_y]) >> 4) << 7) \
195 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
196 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
197 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
199 p_u += *p_offset & b_jump_uv; \
200 p_v += *p_offset++ & b_jump_uv; \
201 *p_pic++ = p_lookup[ \
202 (((*p_y + dither13[i_real_y]) >> 4) << 7) \
203 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
204 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
205 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
207 p_u += *p_offset & b_jump_uv; \
208 p_v += *p_offset++ & b_jump_uv; \
210 /*****************************************************************************
211 * SCALE_WIDTH: scale a line horizontally
212 *****************************************************************************
213 * This macro scales a line using rendering buffer and offset array. It works
214 * for 1, 2 and 4 Bpp.
215 *****************************************************************************/
216 #define SCALE_WIDTH \
217 if( b_horizontal_scaling ) \
219 /* Horizontal scaling, conversion has been done to buffer. \
220 * Rewind buffer and offset, then copy and scale line */ \
221 p_buffer = p_buffer_start; \
222 p_offset = p_offset_start; \
223 for( i_x = i_pic_width / 16; i_x--; ) \
225 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
226 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
227 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
228 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
229 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
230 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
231 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
232 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
233 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
234 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
235 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
236 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
237 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
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++; \
242 p_pic += i_pic_line_width; \
246 /* No scaling, conversion has been done directly in picture memory. \
247 * Increment of picture pointer to end of line is still needed */ \
248 p_pic += i_pic_width + i_pic_line_width; \
252 /*****************************************************************************
253 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
254 *****************************************************************************
255 * This macro scales a line using an offset array.
256 *****************************************************************************/
257 #define SCALE_WIDTH_DITHER( CHROMA ) \
258 if( b_horizontal_scaling ) \
260 /* Horizontal scaling, but we can't use a buffer due to dither */ \
261 p_offset = p_offset_start; \
263 for( i_x = i_pic_width / 16; i_x--; ) \
265 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
266 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
267 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
268 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
273 for( i_x = i_width / 16; i_x--; ) \
275 CONVERT_4YUV_PIXELS( CHROMA ) \
276 CONVERT_4YUV_PIXELS( CHROMA ) \
277 CONVERT_4YUV_PIXELS( CHROMA ) \
278 CONVERT_4YUV_PIXELS( CHROMA ) \
281 /* Increment of picture pointer to end of line is still needed */ \
282 p_pic += i_pic_line_width; \
283 i_real_y = (i_real_y + 1) & 0x3; \
285 /*****************************************************************************
286 * SCALE_HEIGHT: handle vertical scaling
287 *****************************************************************************
288 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
289 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
291 *****************************************************************************/
292 #define SCALE_HEIGHT( CHROMA, BPP ) \
293 /* If line is odd, rewind 4:2:0 U and V samples */ \
294 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
296 p_u -= i_chroma_width; \
297 p_v -= i_chroma_width; \
301 * Handle vertical scaling. The current line can be copied or next one \
304 switch( i_vertical_scaling ) \
306 case -1: /* vertical scaling factor is < 1 */ \
307 while( (i_scale_count -= i_pic_height) >= 0 ) \
309 /* Height reduction: skip next source line */ \
312 if( (CHROMA == 420) || (CHROMA == 422) ) \
316 p_u += i_chroma_width; \
317 p_v += i_chroma_width; \
320 else if( CHROMA == 444 ) \
326 i_scale_count += i_height; \
328 case 1: /* vertical scaling factor is > 1 */ \
329 while( (i_scale_count -= i_height) > 0 ) \
331 /* Height increment: copy previous picture line */ \
332 for( i_x = i_pic_width / 16; i_x--; ) \
334 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
335 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
336 if( BPP > 1 ) /* 2, 3, 4 Bpp */ \
338 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
339 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
341 if( BPP > 2 ) /* 3, 4 Bpp */ \
343 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
344 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
346 if( BPP > 3 ) /* 4 Bpp */ \
348 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
349 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
352 p_pic += i_pic_line_width; \
353 p_pic_start += i_pic_line_width; \
355 i_scale_count += i_pic_height; \
359 /*****************************************************************************
360 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
361 *****************************************************************************
362 * This macro handles vertical scaling for a picture. CHROMA may be 420, 422 or
363 * 444 for RGB conversion, or 400 for gray conversion.
364 *****************************************************************************/
365 #define SCALE_HEIGHT_DITHER( CHROMA ) \
367 /* If line is odd, rewind 4:2:0 U and V samples */ \
368 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
370 p_u -= i_chroma_width; \
371 p_v -= i_chroma_width; \
375 * Handle vertical scaling. The current line can be copied or next one \
379 switch( i_vertical_scaling ) \
381 case -1: /* vertical scaling factor is < 1 */ \
382 while( (i_scale_count -= i_pic_height) >= 0 ) \
384 /* Height reduction: skip next source line */ \
387 if( (CHROMA == 420) || (CHROMA == 422) ) \
391 p_u += i_chroma_width; \
392 p_v += i_chroma_width; \
395 else if( CHROMA == 444 ) \
401 i_scale_count += i_height; \
403 case 1: /* vertical scaling factor is > 1 */ \
404 while( (i_scale_count -= i_height) > 0 ) \
406 SCALE_WIDTH_DITHER( CHROMA ); \
408 p_u -= i_chroma_width; \
409 p_v -= i_chroma_width; \
410 p_pic += i_pic_line_width; \
412 i_scale_count += i_pic_height; \
416 /*****************************************************************************
417 * vout_InitYUV: allocate and initialize translations tables
418 *****************************************************************************
419 * This function will allocate memory to store translation tables, depending
420 * of the screen depth.
421 *****************************************************************************/
422 int vout_InitYUV( vout_thread_t *p_vout )
424 size_t tables_size; /* tables size, in bytes */
426 /* Computes tables size - 3 Bpp use 32 bits pixel entries in tables */
427 switch( p_vout->i_bytes_per_pixel )
430 tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE);
433 tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
438 tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
442 /* Allocate memory */
443 p_vout->yuv.p_base = malloc( tables_size );
444 if( p_vout->yuv.p_base == NULL )
446 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
450 /* Allocate memory for conversion buffer and offset array */
451 p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
452 if( p_vout->yuv.p_buffer == NULL )
454 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
455 free( p_vout->yuv.p_base );
458 p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );
459 if( p_vout->yuv.p_offset == NULL )
461 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
462 free( p_vout->yuv.p_base );
463 free( p_vout->yuv.p_buffer );
467 /* Initialize tables */
472 /*****************************************************************************
473 * vout_ResetTables: re-initialize translations tables
474 *****************************************************************************
475 * This function will initialize the tables allocated by vout_CreateTables and
476 * set functions pointers.
477 *****************************************************************************/
478 int vout_ResetYUV( vout_thread_t *p_vout )
480 vout_EndYUV( p_vout );
481 return( vout_InitYUV( p_vout ) );
484 /*****************************************************************************
485 * vout_EndYUV: destroy translations tables
486 *****************************************************************************
487 * Free memory allocated by vout_CreateTables.
488 *****************************************************************************/
489 void vout_EndYUV( vout_thread_t *p_vout )
491 free( p_vout->yuv.p_base );
492 free( p_vout->yuv.p_buffer );
493 free( p_vout->yuv.p_offset );
496 /* following functions are local */
498 /*****************************************************************************
499 * SetGammaTable: return intensity table transformed by gamma curve.
500 *****************************************************************************
501 * pi_table is a table of 256 entries from 0 to 255.
502 *****************************************************************************/
503 static void SetGammaTable( int *pi_table, double f_gamma )
505 int i_y; /* base intensity */
507 /* Use exp(gamma) instead of gamma */
508 f_gamma = exp( f_gamma );
510 /* Build gamma table */
511 for( i_y = 0; i_y < 256; i_y++ )
513 pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
517 /*****************************************************************************
518 * SetYUV: compute tables and set function pointers
519 + *****************************************************************************/
520 static void SetYUV( vout_thread_t *p_vout )
522 int pi_gamma[256]; /* gamma table */
523 int i_index; /* index in tables */
525 /* Build gamma table */
526 SetGammaTable( pi_gamma, p_vout->f_gamma );
529 * Set pointers and build YUV tables
531 if( p_vout->b_grayscale )
533 /* Grayscale: build gray table */
534 switch( p_vout->i_bytes_per_pixel )
538 u16 bright[256], transp[256];
540 p_vout->yuv.yuv.p_gray8 = (u8 *)p_vout->yuv.p_base + GRAY_MARGIN;
541 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
543 p_vout->yuv.yuv.p_gray8[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
544 p_vout->yuv.yuv.p_gray8[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
546 for( i_index = 0; i_index < 256; i_index++)
548 p_vout->yuv.yuv.p_gray8[ i_index ] = pi_gamma[ i_index ];
549 bright[ i_index ] = i_index << 8;
550 transp[ i_index ] = 0;
552 /* the colors have been allocated, we can set the palette */
553 p_vout->p_set_palette( p_vout, bright, bright, bright, transp );
554 p_vout->i_white_pixel = 0xff;
555 p_vout->i_black_pixel = 0x00;
556 p_vout->i_gray_pixel = 0x44;
557 p_vout->i_blue_pixel = 0x3b;
562 p_vout->yuv.yuv.p_gray16 = (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
563 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
565 p_vout->yuv.yuv.p_gray16[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
566 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
568 for( i_index = 0; i_index < 256; i_index++)
570 p_vout->yuv.yuv.p_gray16[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
575 p_vout->yuv.yuv.p_gray32 = (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
576 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
578 p_vout->yuv.yuv.p_gray32[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
579 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
581 for( i_index = 0; i_index < 256; i_index++)
583 p_vout->yuv.yuv.p_gray32[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
590 /* Color: build red, green and blue tables */
591 switch( p_vout->i_bytes_per_pixel )
597 #define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 )
603 u16 red[256], green[256], blue[256], transp[256];
604 unsigned char lookup[PALETTE_TABLE_SIZE];
606 p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
608 /* this loop calculates the intersection of an YUV box
609 * and the RGB cube. */
610 for ( y = 0; y <= 256; y += 16 )
612 for ( u = 0; u <= 256; u += 32 )
613 for ( v = 0; v <= 256; v += 32 )
615 uvr = (V_RED_COEF*(v-128)) >> SHIFT;
616 uvg = (U_GREEN_COEF*(u-128) + V_GREEN_COEF*(v-128)) >> SHIFT;
617 uvb = (U_BLUE_COEF*(u-128)) >> SHIFT;
622 if( r >= RGB_MIN && g >= RGB_MIN && b >= RGB_MIN
623 && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
625 /* this one should never happen unless someone fscked up my code */
626 if(j == 256) { intf_ErrMsg( "vout error: no colors left to build palette\n" ); break; }
628 /* clip the colors */
630 green[j] = CLIP( g );
636 p_vout->yuv.yuv.p_rgb8[i++] = j;
642 p_vout->yuv.yuv.p_rgb8[i++] = 0;
648 /* the colors have been allocated, we can set the palette */
649 /* there will eventually be a way to know which colors
650 * couldn't be allocated and try to find a replacement */
651 p_vout->p_set_palette( p_vout, red, green, blue, transp );
653 p_vout->i_white_pixel = 0xff;
654 p_vout->i_black_pixel = 0x00;
655 p_vout->i_gray_pixel = 0x44;
656 p_vout->i_blue_pixel = 0x3b;
659 /* this loop allocates colors that got outside
661 for ( y = 0; y <= 256; y += 16 )
663 for ( u = 0; u <= 256; u += 32 )
664 for ( v = 0; v <= 256; v += 32 )
667 int dist, mindist = 100000000;
669 if( lookup[i] || y==0)
676 for( u2 = 0; u2 <= 256; u2 += 32 )
677 for( v2 = 0; v2 <= 256; v2 += 32 )
679 j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
680 dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
682 /* find the nearest color */
685 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
690 /* find the nearest color */
691 if( dist + 128 < mindist )
693 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
694 mindist = dist + 128;
705 p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
706 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
708 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
709 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
711 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
713 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
714 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
716 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
718 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
719 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
721 for( i_index = 0; i_index < 256; i_index++ )
723 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
724 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
725 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
730 p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
731 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
733 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
734 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
736 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
738 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
739 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
741 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
743 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
744 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
746 for( i_index = 0; i_index < 256; i_index++ )
748 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
749 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
750 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
757 * Set functions pointers
759 if( p_vout->b_grayscale )
762 switch( p_vout->i_bytes_per_pixel )
765 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;
766 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;
767 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;
770 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
771 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
772 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
775 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
776 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
777 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
780 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
781 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
782 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
789 switch( p_vout->i_bytes_per_pixel )
792 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
793 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
794 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
797 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB16;
798 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB16;
799 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB16;
802 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB24;
803 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB24;
804 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB24;
807 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB32;
808 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB32;
809 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB32;
815 /*****************************************************************************
816 * SetOffset: build offset array for conversion functions
817 *****************************************************************************
818 * This function will build an offset array used in later conversion functions.
819 * It will also set horizontal and vertical scaling indicators.
820 *****************************************************************************/
821 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
822 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
824 int i_x; /* x position in destination */
825 int i_scale_count; /* modulo counter */
828 * Prepare horizontal offset array
830 if( i_pic_width - i_width > 0 )
832 /* Prepare scaling array for horizontal extension */
834 i_scale_count = i_pic_width;
835 for( i_x = i_width; i_x--; )
837 while( (i_scale_count -= i_width) > 0 )
842 i_scale_count += i_pic_width;
845 else if( i_pic_width - i_width < 0 )
847 /* Prepare scaling array for horizontal reduction */
849 i_scale_count = i_pic_width;
850 for( i_x = i_pic_width; i_x--; )
853 while( (i_scale_count -= i_pic_width) >= 0 )
858 i_scale_count += i_width;
863 /* No horizontal scaling: YUV conversion is done directly to picture */
868 * Set vertical scaling indicator
870 if( i_pic_height - i_height > 0 )
874 else if( i_pic_height - i_height < 0 )
884 /*****************************************************************************
885 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
886 *****************************************************************************/
887 static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
888 yuv_data_t *p_u, yuv_data_t *p_v, int i_width,
889 int i_height, int i_pic_width, int i_pic_height,
890 int i_pic_line_width, int i_matrix_coefficients )
892 boolean_t b_horizontal_scaling; /* horizontal scaling type */
893 int i_vertical_scaling; /* vertical scaling type */
894 int i_x, i_y; /* horizontal and vertical indexes */
895 int i_scale_count; /* scale modulo counter */
896 int i_chroma_width; /* chroma width, not used */
897 u8 * p_gray; /* base conversion table */
898 u8 * p_pic_start; /* beginning of the current line for copy */
899 u8 * p_buffer_start; /* conversion buffer start */
900 u8 * p_buffer; /* conversion buffer pointer */
901 int * p_offset_start; /* offset array start */
902 int * p_offset; /* offset array pointer */
905 * Initialize some values - i_pic_line_width will store the line skip
907 i_pic_line_width -= i_pic_width;
908 p_gray = p_vout->yuv.yuv.p_gray8;
909 p_buffer_start = p_vout->yuv.p_buffer;
910 p_offset_start = p_vout->yuv.p_offset;
911 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
912 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
917 i_scale_count = i_pic_height;
918 for( i_y = 0; i_y < i_height; i_y++ )
920 /* Mark beginnning of line for possible later line copy, and initialize
923 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
925 /* Do YUV conversion to buffer - YUV picture is always formed of 16
926 * pixels wide blocks */
927 for( i_x = i_width / 16; i_x--; )
929 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
930 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
931 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
932 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
933 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
934 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
935 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
936 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
939 /* Do horizontal and vertical scaling */
941 SCALE_HEIGHT(400, 1);
945 /*****************************************************************************
946 * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
947 *****************************************************************************/
948 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,
949 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
950 int i_matrix_coefficients )
952 boolean_t b_horizontal_scaling; /* horizontal scaling type */
953 int i_vertical_scaling; /* vertical scaling type */
954 int i_x, i_y; /* horizontal and vertical indexes */
955 int i_scale_count; /* scale modulo counter */
956 int i_chroma_width; /* chroma width, not used */
957 u16 * p_gray; /* base conversion table */
958 u16 * p_pic_start; /* beginning of the current line for copy */
959 u16 * p_buffer_start; /* conversion buffer start */
960 u16 * p_buffer; /* conversion buffer pointer */
961 int * p_offset_start; /* offset array start */
962 int * p_offset; /* offset array pointer */
965 * Initialize some values - i_pic_line_width will store the line skip
967 i_pic_line_width -= i_pic_width;
968 p_gray = p_vout->yuv.yuv.p_gray16;
969 p_buffer_start = p_vout->yuv.p_buffer;
970 p_offset_start = p_vout->yuv.p_offset;
971 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
972 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
977 i_scale_count = i_pic_height;
978 for( i_y = 0; i_y < i_height; i_y++ )
980 /* Mark beginnning of line for possible later line copy, and initialize
983 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
985 /* Do YUV conversion to buffer - YUV picture is always formed of 16
986 * pixels wide blocks */
987 for( i_x = i_width / 16; i_x--; )
989 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
990 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
991 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
992 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
993 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
994 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
995 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
996 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
999 /* Do horizontal and vertical scaling */
1001 SCALE_HEIGHT(400, 2);
1005 /*****************************************************************************
1006 * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 3 Bpp
1007 *****************************************************************************/
1008 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,
1009 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1010 int i_matrix_coefficients )
1015 /*****************************************************************************
1016 * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
1017 *****************************************************************************/
1018 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,
1019 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1020 int i_matrix_coefficients )
1022 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1023 int i_vertical_scaling; /* vertical scaling type */
1024 int i_x, i_y; /* horizontal and vertical indexes */
1025 int i_scale_count; /* scale modulo counter */
1026 int i_chroma_width; /* chroma width, not used */
1027 u32 * p_gray; /* base conversion table */
1028 u32 * p_pic_start; /* beginning of the current line for copy */
1029 u32 * p_buffer_start; /* conversion buffer start */
1030 u32 * p_buffer; /* conversion buffer pointer */
1031 int * p_offset_start; /* offset array start */
1032 int * p_offset; /* offset array pointer */
1035 * Initialize some values - i_pic_line_width will store the line skip
1037 i_pic_line_width -= i_pic_width;
1038 p_gray = p_vout->yuv.yuv.p_gray32;
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 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1060 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1061 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1062 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1063 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1064 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1065 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1066 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1069 /* Do horizontal and vertical scaling */
1071 SCALE_HEIGHT(400, 4);
1075 /*****************************************************************************
1076 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
1077 *****************************************************************************/
1078 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,
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 b_jump_uv; /* should we jump u and v ? */
1087 int i_real_y; /* y % 4 */
1088 u8 * p_lookup; /* lookup table */
1089 int i_chroma_width; /* chroma width */
1090 int * p_offset_start; /* offset array start */
1091 int * p_offset; /* offset array pointer */
1093 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
1094 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
1095 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
1096 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
1098 int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
1099 int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
1100 int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
1101 int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
1103 /* other matrices that can be interesting, either for debugging or for effects */
1105 int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
1106 int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
1107 int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
1108 int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
1109 int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
1110 int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
1114 * Initialize some values - i_pic_line_width will store the line skip
1116 i_pic_line_width -= i_pic_width;
1117 i_chroma_width = i_width / 2;
1118 p_offset_start = p_vout->yuv.p_offset;
1119 p_lookup = p_vout->yuv.p_base;
1120 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1121 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1124 * Perform conversion
1126 i_scale_count = i_pic_height;
1128 for( i_y = 0; i_y < i_height; i_y++ )
1130 /* Do horizontal and vertical scaling */
1131 SCALE_WIDTH_DITHER( 420 );
1132 SCALE_HEIGHT_DITHER( 420 );
1136 /*****************************************************************************
1137 * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1138 *****************************************************************************/
1139 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,
1140 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1141 int i_matrix_coefficients )
1143 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1144 int i_vertical_scaling; /* vertical scaling type */
1145 int i_x, i_y; /* horizontal and vertical indexes */
1146 int i_scale_count; /* scale modulo counter */
1147 int i_uval, i_vval; /* U and V samples */
1148 int i_red, i_green, i_blue; /* U and V modified samples */
1149 int i_chroma_width; /* chroma width */
1150 u8 * p_yuv; /* base conversion table */
1151 u8 * p_ybase; /* Y dependant conversion table */
1152 u8 * p_pic_start; /* beginning of the current line for copy */
1153 u8 * p_buffer_start; /* conversion buffer start */
1154 u8 * p_buffer; /* conversion buffer pointer */
1155 int * p_offset_start; /* offset array start */
1156 int * p_offset; /* offset array pointer */
1159 * Initialize some values - i_pic_line_width will store the line skip
1161 i_pic_line_width -= i_pic_width;
1162 i_chroma_width = i_width / 2;
1163 p_yuv = p_vout->yuv.yuv.p_rgb8;
1164 p_buffer_start = p_vout->yuv.p_buffer;
1165 p_offset_start = p_vout->yuv.p_offset;
1166 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1167 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1170 * Perform conversion
1172 i_scale_count = i_pic_height;
1173 for( i_y = 0; i_y < i_height; i_y++ )
1175 /* Mark beginnning of line for possible later line copy, and initialize
1177 p_pic_start = p_pic;
1178 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1180 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1181 * pixels wide blocks */
1182 for( i_x = i_width / 16; i_x--; )
1184 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1185 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1186 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1187 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1188 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1189 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1190 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1191 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1194 /* Do horizontal and vertical scaling */
1196 SCALE_HEIGHT(422, 1);
1200 /*****************************************************************************
1201 * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1202 *****************************************************************************/
1203 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,
1204 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1205 int i_matrix_coefficients )
1207 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1208 int i_vertical_scaling; /* vertical scaling type */
1209 int i_x, i_y; /* horizontal and vertical indexes */
1210 int i_scale_count; /* scale modulo counter */
1211 int i_uval, i_vval; /* U and V samples */
1212 int i_red, i_green, i_blue; /* U and V modified samples */
1213 int i_chroma_width; /* chroma width, not used */
1214 u8 * p_yuv; /* base conversion table */
1215 u8 * p_ybase; /* Y dependant conversion table */
1216 u8 * p_pic_start; /* beginning of the current line for copy */
1217 u8 * p_buffer_start; /* conversion buffer start */
1218 u8 * p_buffer; /* conversion buffer pointer */
1219 int * p_offset_start; /* offset array start */
1220 int * p_offset; /* offset array pointer */
1223 * Initialize some values - i_pic_line_width will store the line skip
1225 i_pic_line_width -= i_pic_width;
1226 p_yuv = p_vout->yuv.yuv.p_rgb8;
1227 p_buffer_start = p_vout->yuv.p_buffer;
1228 p_offset_start = p_vout->yuv.p_offset;
1229 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1230 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1233 * Perform conversion
1235 i_scale_count = i_pic_height;
1236 for( i_y = 0; i_y < i_height; i_y++ )
1238 /* Mark beginnning of line for possible later line copy, and initialize
1240 p_pic_start = p_pic;
1241 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1243 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1244 * pixels wide blocks */
1245 for( i_x = i_width / 16; i_x--; )
1247 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1248 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1249 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1250 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1251 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1252 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1253 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1254 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1257 /* Do horizontal and vertical scaling */
1259 SCALE_HEIGHT(444, 1);
1263 /*****************************************************************************
1264 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1265 *****************************************************************************/
1266 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,
1267 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1268 int i_matrix_coefficients )
1272 int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
1274 i_chroma_width = i_width / 2;
1275 i_chroma_skip = i_skip / 2;
1276 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1277 (i_width + i_skip) * sizeof( yuv_data_t ),
1278 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1279 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1280 p_vout->i_screen_depth == 15 );
1282 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1283 int i_vertical_scaling; /* vertical scaling type */
1284 int i_x, i_y; /* horizontal and vertical indexes */
1285 int i_scale_count; /* scale modulo counter */
1286 int i_uval, i_vval; /* U and V samples */
1287 int i_red, i_green, i_blue; /* U and V modified samples */
1288 int i_chroma_width; /* chroma width */
1289 u16 * p_yuv; /* base conversion table */
1290 u16 * p_ybase; /* Y dependant conversion table */
1291 u16 * p_pic_start; /* beginning of the current line for copy */
1292 u16 * p_buffer_start; /* conversion buffer start */
1293 u16 * p_buffer; /* conversion buffer pointer */
1294 int * p_offset_start; /* offset array start */
1295 int * p_offset; /* offset array pointer */
1298 * Initialize some values - i_pic_line_width will store the line skip
1300 i_pic_line_width -= i_pic_width;
1301 i_chroma_width = i_width / 2;
1302 p_yuv = p_vout->yuv.yuv.p_rgb16;
1303 p_buffer_start = p_vout->yuv.p_buffer;
1304 p_offset_start = p_vout->yuv.p_offset;
1305 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1306 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1309 * Perform conversion
1311 i_scale_count = i_pic_height;
1312 for( i_y = 0; i_y < i_height; i_y++ )
1314 /* Mark beginnning of line for possible later line copy, and initialize
1316 p_pic_start = p_pic;
1317 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1319 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1320 * pixels wide blocks */
1321 for( i_x = i_width / 16; i_x--; )
1323 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1324 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1325 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1326 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1327 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1328 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1329 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1330 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1333 /* Do horizontal and vertical scaling */
1335 SCALE_HEIGHT(420, 2);
1339 /*****************************************************************************
1340 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1341 *****************************************************************************/
1342 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,
1343 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1344 int i_matrix_coefficients )
1346 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1347 int i_vertical_scaling; /* vertical scaling type */
1348 int i_x, i_y; /* horizontal and vertical indexes */
1349 int i_scale_count; /* scale modulo counter */
1350 int i_uval, i_vval; /* U and V samples */
1351 int i_red, i_green, i_blue; /* U and V modified samples */
1352 int i_chroma_width; /* chroma width */
1353 u16 * p_yuv; /* base conversion table */
1354 u16 * p_ybase; /* Y dependant conversion table */
1355 u16 * p_pic_start; /* beginning of the current line for copy */
1356 u16 * p_buffer_start; /* conversion buffer start */
1357 u16 * p_buffer; /* conversion buffer pointer */
1358 int * p_offset_start; /* offset array start */
1359 int * p_offset; /* offset array pointer */
1362 * Initialize some values - i_pic_line_width will store the line skip
1364 i_pic_line_width -= i_pic_width;
1365 i_chroma_width = i_width / 2;
1366 p_yuv = p_vout->yuv.yuv.p_rgb16;
1367 p_buffer_start = p_vout->yuv.p_buffer;
1368 p_offset_start = p_vout->yuv.p_offset;
1369 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1370 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1373 * Perform conversion
1375 i_scale_count = i_pic_height;
1376 for( i_y = 0; i_y < i_height; i_y++ )
1378 /* Mark beginnning of line for possible later line copy, and initialize
1380 p_pic_start = p_pic;
1381 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1383 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1384 * pixels wide blocks */
1385 for( i_x = i_width / 16; i_x--; )
1387 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1388 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1389 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1390 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1391 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1392 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1393 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1394 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1397 /* Do horizontal and vertical scaling */
1399 SCALE_HEIGHT(422, 2);
1403 /*****************************************************************************
1404 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1405 *****************************************************************************/
1406 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,
1407 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1408 int i_matrix_coefficients )
1410 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1411 int i_vertical_scaling; /* vertical scaling type */
1412 int i_x, i_y; /* horizontal and vertical indexes */
1413 int i_scale_count; /* scale modulo counter */
1414 int i_uval, i_vval; /* U and V samples */
1415 int i_red, i_green, i_blue; /* U and V modified samples */
1416 int i_chroma_width; /* chroma width, not used */
1417 u16 * p_yuv; /* base conversion table */
1418 u16 * p_ybase; /* Y dependant conversion table */
1419 u16 * p_pic_start; /* beginning of the current line for copy */
1420 u16 * p_buffer_start; /* conversion buffer start */
1421 u16 * p_buffer; /* conversion buffer pointer */
1422 int * p_offset_start; /* offset array start */
1423 int * p_offset; /* offset array pointer */
1426 * Initialize some values - i_pic_line_width will store the line skip
1428 i_pic_line_width -= i_pic_width;
1429 p_yuv = p_vout->yuv.yuv.p_rgb16;
1430 p_buffer_start = p_vout->yuv.p_buffer;
1431 p_offset_start = p_vout->yuv.p_offset;
1432 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1433 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1436 * Perform conversion
1438 i_scale_count = i_pic_height;
1439 for( i_y = 0; i_y < i_height; i_y++ )
1441 /* Mark beginnning of line for possible later line copy, and initialize
1443 p_pic_start = p_pic;
1444 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1446 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1447 * pixels wide blocks */
1448 for( i_x = i_width / 16; i_x--; )
1450 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1451 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1452 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1453 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1454 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1455 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1456 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1457 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1460 /* Do horizontal and vertical scaling */
1462 SCALE_HEIGHT(444, 2);
1466 /*****************************************************************************
1467 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1468 *****************************************************************************/
1469 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,
1470 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1471 int i_matrix_coefficients )
1476 /*****************************************************************************
1477 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1478 *****************************************************************************/
1479 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,
1480 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1481 int i_matrix_coefficients )
1486 /*****************************************************************************
1487 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1488 *****************************************************************************/
1489 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,
1490 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1491 int i_matrix_coefficients )
1496 /*****************************************************************************
1497 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1498 *****************************************************************************/
1499 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,
1500 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1501 int i_matrix_coefficients )
1503 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1504 int i_vertical_scaling; /* vertical scaling type */
1505 int i_x, i_y; /* horizontal and vertical indexes */
1506 int i_scale_count; /* scale modulo counter */
1507 int i_uval, i_vval; /* U and V samples */
1508 int i_red, i_green, i_blue; /* U and V modified samples */
1509 int i_chroma_width; /* chroma width */
1510 u32 * p_yuv; /* base conversion table */
1511 u32 * p_ybase; /* Y dependant conversion table */
1512 u32 * p_pic_start; /* beginning of the current line for copy */
1513 u32 * p_buffer_start; /* conversion buffer start */
1514 u32 * p_buffer; /* conversion buffer pointer */
1515 int * p_offset_start; /* offset array start */
1516 int * p_offset; /* offset array pointer */
1519 * Initialize some values - i_pic_line_width will store the line skip
1521 i_pic_line_width -= i_pic_width;
1522 i_chroma_width = i_width / 2;
1523 p_yuv = p_vout->yuv.yuv.p_rgb32;
1524 p_buffer_start = p_vout->yuv.p_buffer;
1525 p_offset_start = p_vout->yuv.p_offset;
1526 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1527 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1530 * Perform conversion
1532 i_scale_count = i_pic_height;
1533 for( i_y = 0; i_y < i_height; i_y++ )
1535 /* Mark beginnning of line for possible later line copy, and initialize
1537 p_pic_start = p_pic;
1538 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1540 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1541 * pixels wide blocks */
1542 for( i_x = i_width / 16; i_x--; )
1544 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1545 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1546 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1547 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1548 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1549 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1550 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1551 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1554 /* Do horizontal and vertical scaling */
1556 SCALE_HEIGHT(420, 4);
1560 /*****************************************************************************
1561 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1562 *****************************************************************************/
1563 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,
1564 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1565 int i_matrix_coefficients )
1567 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1568 int i_vertical_scaling; /* vertical scaling type */
1569 int i_x, i_y; /* horizontal and vertical indexes */
1570 int i_scale_count; /* scale modulo counter */
1571 int i_uval, i_vval; /* U and V samples */
1572 int i_red, i_green, i_blue; /* U and V modified samples */
1573 int i_chroma_width; /* chroma width */
1574 u32 * p_yuv; /* base conversion table */
1575 u32 * p_ybase; /* Y dependant conversion table */
1576 u32 * p_pic_start; /* beginning of the current line for copy */
1577 u32 * p_buffer_start; /* conversion buffer start */
1578 u32 * p_buffer; /* conversion buffer pointer */
1579 int * p_offset_start; /* offset array start */
1580 int * p_offset; /* offset array pointer */
1583 * Initialize some values - i_pic_line_width will store the line skip
1585 i_pic_line_width -= i_pic_width;
1586 i_chroma_width = i_width / 2;
1587 p_yuv = p_vout->yuv.yuv.p_rgb32;
1588 p_buffer_start = p_vout->yuv.p_buffer;
1589 p_offset_start = p_vout->yuv.p_offset;
1590 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1591 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1594 * Perform conversion
1596 i_scale_count = i_pic_height;
1597 for( i_y = 0; i_y < i_height; i_y++ )
1599 /* Mark beginnning of line for possible later line copy, and initialize
1601 p_pic_start = p_pic;
1602 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1604 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1605 * pixels wide blocks */
1606 for( i_x = i_width / 16; i_x--; )
1608 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1609 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1610 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1611 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1612 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1613 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1614 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1615 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1618 /* Do horizontal and vertical scaling */
1620 SCALE_HEIGHT(422, 4);
1624 /*****************************************************************************
1625 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1626 *****************************************************************************/
1627 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,
1628 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1629 int i_matrix_coefficients )
1631 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1632 int i_vertical_scaling; /* vertical scaling type */
1633 int i_x, i_y; /* horizontal and vertical indexes */
1634 int i_scale_count; /* scale modulo counter */
1635 int i_uval, i_vval; /* U and V samples */
1636 int i_red, i_green, i_blue; /* U and V modified samples */
1637 int i_chroma_width; /* chroma width, not used */
1638 u32 * p_yuv; /* base conversion table */
1639 u32 * p_ybase; /* Y dependant conversion table */
1640 u32 * p_pic_start; /* beginning of the current line for copy */
1641 u32 * p_buffer_start; /* conversion buffer start */
1642 u32 * p_buffer; /* conversion buffer pointer */
1643 int * p_offset_start; /* offset array start */
1644 int * p_offset; /* offset array pointer */
1647 * Initialize some values - i_pic_line_width will store the line skip
1649 i_pic_line_width -= i_pic_width;
1650 p_yuv = p_vout->yuv.yuv.p_rgb32;
1651 p_buffer_start = p_vout->yuv.p_buffer;
1652 p_offset_start = p_vout->yuv.p_offset;
1653 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1654 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1657 * Perform conversion
1659 i_scale_count = i_pic_height;
1660 for( i_y = 0; i_y < i_height; i_y++ )
1662 /* Mark beginnning of line for possible later line copy, and initialize
1664 p_pic_start = p_pic;
1665 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1667 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1668 * pixels wide blocks */
1669 for( i_x = i_width / 16; i_x--; )
1671 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1672 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1673 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1674 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1675 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1676 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1677 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1678 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1681 /* Do horizontal and vertical scaling */
1683 SCALE_HEIGHT(444, 4);
1687 /*-------------------- walken code follows ----------------------------------*/
1690 * YUV to RGB routines.
1692 * these routines calculate r, g and b values from each pixel's y, u and v.
1693 * these r, g an b values are then passed thru a table lookup to take the
1694 * gamma curve into account and find the corresponding pixel value.
1696 * the table must store more than 3*256 values because of the possibility
1697 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1698 * values are in the following intervals :
1699 * -176 to 255+176 for red
1700 * -133 to 255+133 for green
1701 * -222 to 255+222 for blue
1703 * If the input y,u,v values are right, the r,g,b results are not expected
1704 * to move out of the 0 to 255 interval but who knows what will happen in
1707 * the red, green and blue conversion tables are stored in a single 1935-entry
1708 * array. The respective positions of each component in the array have been
1709 * calculated to minimize the cache interactions of the 3 tables.
1714 static void yuvToRgb24 (unsigned char * Y,
1715 unsigned char * U, unsigned char * V,
1716 char * dest, int table[1935], int width)
1731 uvRed = (V_RED_COEF*v) >> SHIFT;
1732 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1733 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1735 tableY = table + *(Y++);
1736 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1737 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1739 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1741 *(dest++) = tmp24 >> 8;
1742 *(dest++) = tmp24 >> 16;
1744 tableY = table + *(Y++);
1745 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1746 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1748 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1750 *(dest++) = tmp24 >> 8;
1751 *(dest++) = tmp24 >> 16;
1755 uvRed = (V_RED_COEF*v) >> SHIFT;
1756 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1757 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1759 tableY = table + *(Y++);
1760 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1761 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1763 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1765 *(dest++) = tmp24 >> 8;
1766 *(dest++) = tmp24 >> 16;
1768 tableY = table + *(Y++);
1769 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1770 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1772 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1774 *(dest++) = tmp24 >> 8;
1775 *(dest++) = tmp24 >> 16;
1779 uvRed = (V_RED_COEF*v) >> SHIFT;
1780 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1781 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1783 tableY = table + *(Y++);
1784 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1785 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1787 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1789 *(dest++) = tmp24 >> 8;
1790 *(dest++) = tmp24 >> 16;
1792 tableY = table + *(Y++);
1793 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1794 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1796 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1798 *(dest++) = tmp24 >> 8;
1799 *(dest++) = tmp24 >> 16;
1803 uvRed = (V_RED_COEF*v) >> SHIFT;
1804 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1805 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1807 tableY = table + *(Y++);
1808 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1809 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1811 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1813 *(dest++) = tmp24 >> 8;
1814 *(dest++) = tmp24 >> 16;
1816 tableY = table + *(Y++);
1817 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1818 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1820 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1822 *(dest++) = tmp24 >> 8;
1823 *(dest++) = tmp24 >> 16;
1826 i = (width & 7) >> 1;
1830 uvRed = (V_RED_COEF*v) >> SHIFT;
1831 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1832 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1834 tableY = table + *(Y++);
1835 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1836 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1838 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1840 *(dest++) = tmp24 >> 8;
1841 *(dest++) = tmp24 >> 16;
1843 tableY = table + *(Y++);
1844 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1845 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1847 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1849 *(dest++) = tmp24 >> 8;
1850 *(dest++) = tmp24 >> 16;
1856 uvRed = (V_RED_COEF*v) >> SHIFT;
1857 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1858 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1860 tableY = table + *(Y++);
1861 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1862 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1864 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1866 *(dest++) = tmp24 >> 8;
1867 *(dest++) = tmp24 >> 16;