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 *****************************************************************************/
32 #include <math.h> /* exp(), pow() */
33 #include <errno.h> /* ENOMEM */
34 #include <stdlib.h> /* free() */
35 #include <string.h> /* strerror() */
43 #include "video_output.h"
44 #include "video_yuv.h"
48 /*****************************************************************************
50 *****************************************************************************/
52 /* Margins and offsets in conversion tables - Margins are used in case a RGB
53 * RGB conversion would give a value outside the 0-255 range. Offsets have been
54 * calculated to avoid using the same cache line for 2 tables. conversion tables
55 * are 2*MARGIN + 256 long and stores pixels.*/
56 #define RED_MARGIN 178
57 #define GREEN_MARGIN 135
58 #define BLUE_MARGIN 224
59 #define RED_OFFSET 1501 /* 1323 to 1935 */
60 #define GREEN_OFFSET 135 /* 0 to 526 */
61 #define BLUE_OFFSET 818 /* 594 to 1298 */
62 #define RGB_TABLE_SIZE 1935 /* total table size */
64 #define GRAY_MARGIN 384
65 #define GRAY_TABLE_SIZE 1024 /* total table size */
67 #define PALETTE_TABLE_SIZE 2176 /* YUV -> 8bpp palette lookup table */
69 /* macros used for YUV pixel conversions */
71 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
72 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
73 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
74 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
78 /*****************************************************************************
80 *****************************************************************************/
81 static void SetGammaTable ( int *pi_table, double f_gamma );
82 static void SetYUV ( vout_thread_t *p_vout );
83 static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height,
84 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
86 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 );
113 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,
114 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
115 int i_matrix_coefficients );
116 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,
117 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
118 int i_matrix_coefficients );
119 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,
120 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
121 int i_matrix_coefficients );
122 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,
123 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
124 int i_matrix_coefficients );
125 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,
126 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
127 int i_matrix_coefficients );
128 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,
129 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
130 int i_matrix_coefficients );
131 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,
132 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
133 int i_matrix_coefficients );
135 /*****************************************************************************
136 * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel conversion blocks
137 *****************************************************************************
138 * These conversion routines are used by YUV conversion functions.
139 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
140 * which is also modified.
141 *****************************************************************************/
142 #define CONVERT_Y_PIXEL( BPP ) \
143 /* Only Y sample is present */ \
144 p_ybase = p_yuv + *p_y++; \
145 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
146 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
147 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
149 #define CONVERT_YUV_PIXEL( BPP ) \
150 /* Y, U and V samples are present */ \
153 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
154 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
155 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
156 CONVERT_Y_PIXEL( BPP ) \
158 /*****************************************************************************
159 * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp
160 *****************************************************************************
161 * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
162 *****************************************************************************/
163 #define CONVERT_4YUV_PIXELS( CHROMA ) \
164 *p_pic++ = p_lookup[ \
165 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
166 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
167 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
168 *p_pic++ = p_lookup[ \
169 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
170 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
171 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
172 *p_pic++ = p_lookup[ \
173 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
174 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
175 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
176 *p_pic++ = p_lookup[ \
177 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
178 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
179 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
181 #define CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
182 *p_pic++ = p_lookup[ \
183 (((*p_y + dither10[i_real_y]) >> 4) << 7) \
184 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
185 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
186 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
188 p_u += *p_offset & b_jump_uv; \
189 p_v += *p_offset++ & b_jump_uv; \
190 *p_pic++ = p_lookup[ \
191 (((*p_y + dither11[i_real_y]) >> 4) << 7) \
192 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
193 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
194 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
196 p_u += *p_offset & b_jump_uv; \
197 p_v += *p_offset++ & b_jump_uv; \
198 *p_pic++ = p_lookup[ \
199 (((*p_y + dither12[i_real_y]) >> 4) << 7) \
200 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
201 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
202 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
204 p_u += *p_offset & b_jump_uv; \
205 p_v += *p_offset++ & b_jump_uv; \
206 *p_pic++ = p_lookup[ \
207 (((*p_y + dither13[i_real_y]) >> 4) << 7) \
208 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
209 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
210 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
212 p_u += *p_offset & b_jump_uv; \
213 p_v += *p_offset++ & b_jump_uv; \
215 /*****************************************************************************
216 * SCALE_WIDTH: scale a line horizontally
217 *****************************************************************************
218 * This macro scales a line using rendering buffer and offset array. It works
219 * for 1, 2 and 4 Bpp.
220 *****************************************************************************/
221 #define SCALE_WIDTH \
222 if( b_horizontal_scaling ) \
224 /* Horizontal scaling, conversion has been done to buffer. \
225 * Rewind buffer and offset, then copy and scale line */ \
226 p_buffer = p_buffer_start; \
227 p_offset = p_offset_start; \
228 for( i_x = i_pic_width / 16; i_x--; ) \
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++; \
241 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
242 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
243 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
244 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
245 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
247 p_pic += i_pic_line_width; \
251 /* No scaling, conversion has been done directly in picture memory. \
252 * Increment of picture pointer to end of line is still needed */ \
253 p_pic += i_pic_width + i_pic_line_width; \
257 /*****************************************************************************
258 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
259 *****************************************************************************
260 * This macro scales a line using an offset array.
261 *****************************************************************************/
262 #define SCALE_WIDTH_DITHER( CHROMA ) \
263 if( b_horizontal_scaling ) \
265 /* Horizontal scaling, but we can't use a buffer due to dither */ \
266 p_offset = p_offset_start; \
268 for( i_x = i_pic_width / 16; i_x--; ) \
270 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
271 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
272 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
273 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
278 for( i_x = i_width / 16; i_x--; ) \
280 CONVERT_4YUV_PIXELS( CHROMA ) \
281 CONVERT_4YUV_PIXELS( CHROMA ) \
282 CONVERT_4YUV_PIXELS( CHROMA ) \
283 CONVERT_4YUV_PIXELS( CHROMA ) \
286 /* Increment of picture pointer to end of line is still needed */ \
287 p_pic += i_pic_line_width; \
288 i_real_y = (i_real_y + 1) & 0x3; \
290 /*****************************************************************************
291 * SCALE_HEIGHT: handle vertical scaling
292 *****************************************************************************
293 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
294 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
296 *****************************************************************************/
297 #define SCALE_HEIGHT( CHROMA, BPP ) \
298 /* If line is odd, rewind 4:2:0 U and V samples */ \
299 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
301 p_u -= i_chroma_width; \
302 p_v -= i_chroma_width; \
306 * Handle vertical scaling. The current line can be copied or next one \
309 switch( i_vertical_scaling ) \
311 case -1: /* vertical scaling factor is < 1 */ \
312 while( (i_scale_count -= i_pic_height) >= 0 ) \
314 /* Height reduction: skip next source line */ \
317 if( (CHROMA == 420) || (CHROMA == 422) ) \
321 p_u += i_chroma_width; \
322 p_v += i_chroma_width; \
325 else if( CHROMA == 444 ) \
331 i_scale_count += i_height; \
333 case 1: /* vertical scaling factor is > 1 */ \
334 while( (i_scale_count -= i_height) > 0 ) \
336 /* Height increment: copy previous picture line */ \
337 for( i_x = i_pic_width / 16; i_x--; ) \
339 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
340 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
341 if( BPP > 1 ) /* 2, 3, 4 Bpp */ \
343 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
344 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
346 if( BPP > 2 ) /* 3, 4 Bpp */ \
348 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
349 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
351 if( BPP > 3 ) /* 4 Bpp */ \
353 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
354 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
357 p_pic += i_pic_line_width; \
358 p_pic_start += i_pic_line_width; \
360 i_scale_count += i_pic_height; \
364 /*****************************************************************************
365 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
366 *****************************************************************************
367 * This macro handles vertical scaling for a picture. CHROMA may be 420, 422 or
368 * 444 for RGB conversion, or 400 for gray conversion.
369 *****************************************************************************/
370 #define SCALE_HEIGHT_DITHER( CHROMA ) \
372 /* If line is odd, rewind 4:2:0 U and V samples */ \
373 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
375 p_u -= i_chroma_width; \
376 p_v -= i_chroma_width; \
380 * Handle vertical scaling. The current line can be copied or next one \
384 switch( i_vertical_scaling ) \
386 case -1: /* vertical scaling factor is < 1 */ \
387 while( (i_scale_count -= i_pic_height) >= 0 ) \
389 /* Height reduction: skip next source line */ \
392 if( (CHROMA == 420) || (CHROMA == 422) ) \
396 p_u += i_chroma_width; \
397 p_v += i_chroma_width; \
400 else if( CHROMA == 444 ) \
406 i_scale_count += i_height; \
408 case 1: /* vertical scaling factor is > 1 */ \
409 while( (i_scale_count -= i_height) > 0 ) \
411 SCALE_WIDTH_DITHER( CHROMA ); \
413 p_u -= i_chroma_width; \
414 p_v -= i_chroma_width; \
415 p_pic += i_pic_line_width; \
417 i_scale_count += i_pic_height; \
421 /*****************************************************************************
422 * vout_InitYUV: allocate and initialize translations tables
423 *****************************************************************************
424 * This function will allocate memory to store translation tables, depending
425 * of the screen depth.
426 *****************************************************************************/
427 int vout_InitYUV( vout_thread_t *p_vout )
429 size_t tables_size; /* tables size, in bytes */
431 /* Computes tables size - 3 Bpp use 32 bits pixel entries in tables */
432 switch( p_vout->i_bytes_per_pixel )
435 tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE);
438 tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
443 tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
447 /* Allocate memory */
448 p_vout->yuv.p_base = malloc( tables_size );
449 if( p_vout->yuv.p_base == NULL )
451 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
455 /* Allocate memory for conversion buffer and offset array */
456 p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
457 if( p_vout->yuv.p_buffer == NULL )
459 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
460 free( p_vout->yuv.p_base );
463 p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );
464 if( p_vout->yuv.p_offset == NULL )
466 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
467 free( p_vout->yuv.p_base );
468 free( p_vout->yuv.p_buffer );
472 /* Initialize tables */
477 /*****************************************************************************
478 * vout_ResetTables: re-initialize translations tables
479 *****************************************************************************
480 * This function will initialize the tables allocated by vout_CreateTables and
481 * set functions pointers.
482 *****************************************************************************/
483 int vout_ResetYUV( vout_thread_t *p_vout )
485 vout_EndYUV( p_vout );
486 return( vout_InitYUV( p_vout ) );
489 /*****************************************************************************
490 * vout_EndYUV: destroy translations tables
491 *****************************************************************************
492 * Free memory allocated by vout_CreateTables.
493 *****************************************************************************/
494 void vout_EndYUV( vout_thread_t *p_vout )
496 free( p_vout->yuv.p_base );
497 free( p_vout->yuv.p_buffer );
498 free( p_vout->yuv.p_offset );
501 /* following functions are local */
503 /*****************************************************************************
504 * SetGammaTable: return intensity table transformed by gamma curve.
505 *****************************************************************************
506 * pi_table is a table of 256 entries from 0 to 255.
507 *****************************************************************************/
508 static void SetGammaTable( int *pi_table, double f_gamma )
510 int i_y; /* base intensity */
512 /* Use exp(gamma) instead of gamma */
513 f_gamma = exp( f_gamma );
515 /* Build gamma table */
516 for( i_y = 0; i_y < 256; i_y++ )
518 pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
522 /*****************************************************************************
523 * SetYUV: compute tables and set function pointers
524 + *****************************************************************************/
525 static void SetYUV( vout_thread_t *p_vout )
527 int pi_gamma[256]; /* gamma table */
528 int i_index; /* index in tables */
530 /* Build gamma table */
531 SetGammaTable( pi_gamma, p_vout->f_gamma );
534 * Set pointers and build YUV tables
536 if( p_vout->b_grayscale )
538 /* Grayscale: build gray table */
539 switch( p_vout->i_bytes_per_pixel )
543 u16 bright[256], transp[256];
545 p_vout->yuv.yuv.p_gray8 = (u8 *)p_vout->yuv.p_base + GRAY_MARGIN;
546 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
548 p_vout->yuv.yuv.p_gray8[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
549 p_vout->yuv.yuv.p_gray8[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
551 for( i_index = 0; i_index < 256; i_index++)
553 p_vout->yuv.yuv.p_gray8[ i_index ] = pi_gamma[ i_index ];
554 bright[ i_index ] = i_index << 8;
555 transp[ i_index ] = 0;
557 /* the colors have been allocated, we can set the palette */
558 p_vout->p_set_palette( p_vout, bright, bright, bright, transp );
559 p_vout->i_white_pixel = 0xff;
560 p_vout->i_black_pixel = 0x00;
561 p_vout->i_gray_pixel = 0x44;
562 p_vout->i_blue_pixel = 0x3b;
567 p_vout->yuv.yuv.p_gray16 = (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
568 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
570 p_vout->yuv.yuv.p_gray16[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
571 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
573 for( i_index = 0; i_index < 256; i_index++)
575 p_vout->yuv.yuv.p_gray16[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
580 p_vout->yuv.yuv.p_gray32 = (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
581 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
583 p_vout->yuv.yuv.p_gray32[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
584 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
586 for( i_index = 0; i_index < 256; i_index++)
588 p_vout->yuv.yuv.p_gray32[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
595 /* Color: build red, green and blue tables */
596 switch( p_vout->i_bytes_per_pixel )
602 #define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 )
608 u16 red[256], green[256], blue[256], transp[256];
609 unsigned char lookup[PALETTE_TABLE_SIZE];
611 p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
613 /* this loop calculates the intersection of an YUV box
614 * and the RGB cube. */
615 for ( y = 0; y <= 256; y += 16 )
617 for ( u = 0; u <= 256; u += 32 )
618 for ( v = 0; v <= 256; v += 32 )
620 uvr = (V_RED_COEF*(v-128)) >> SHIFT;
621 uvg = (U_GREEN_COEF*(u-128) + V_GREEN_COEF*(v-128)) >> SHIFT;
622 uvb = (U_BLUE_COEF*(u-128)) >> SHIFT;
627 if( r >= RGB_MIN && g >= RGB_MIN && b >= RGB_MIN
628 && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
630 /* this one should never happen unless someone fscked up my code */
631 if(j == 256) { intf_ErrMsg( "vout error: no colors left to build palette\n" ); break; }
633 /* clip the colors */
635 green[j] = CLIP( g );
641 p_vout->yuv.yuv.p_rgb8[i++] = j;
647 p_vout->yuv.yuv.p_rgb8[i++] = 0;
653 /* the colors have been allocated, we can set the palette */
654 /* there will eventually be a way to know which colors
655 * couldn't be allocated and try to find a replacement */
656 p_vout->p_set_palette( p_vout, red, green, blue, transp );
658 p_vout->i_white_pixel = 0xff;
659 p_vout->i_black_pixel = 0x00;
660 p_vout->i_gray_pixel = 0x44;
661 p_vout->i_blue_pixel = 0x3b;
664 /* this loop allocates colors that got outside
666 for ( y = 0; y <= 256; y += 16 )
668 for ( u = 0; u <= 256; u += 32 )
669 for ( v = 0; v <= 256; v += 32 )
672 int dist, mindist = 100000000;
674 if( lookup[i] || y==0)
681 for( u2 = 0; u2 <= 256; u2 += 32 )
682 for( v2 = 0; v2 <= 256; v2 += 32 )
684 j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
685 dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
687 /* find the nearest color */
690 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
695 /* find the nearest color */
696 if( dist + 128 < mindist )
698 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
699 mindist = dist + 128;
710 p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
711 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
713 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
714 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
716 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
718 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
719 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
721 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
723 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
724 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
726 for( i_index = 0; i_index < 256; i_index++ )
728 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
729 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
730 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
735 p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
736 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
738 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
739 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
741 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
743 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
744 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
746 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
748 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
749 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
751 for( i_index = 0; i_index < 256; i_index++ )
753 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
754 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
755 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
762 * Set functions pointers
764 if( p_vout->b_grayscale )
767 switch( p_vout->i_bytes_per_pixel )
770 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;
771 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;
772 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;
775 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
776 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
777 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
780 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
781 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
782 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
785 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
786 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
787 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
794 switch( p_vout->i_bytes_per_pixel )
797 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
798 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
799 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
802 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB16;
803 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB16;
804 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB16;
807 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB24;
808 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB24;
809 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB24;
812 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB32;
813 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB32;
814 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB32;
820 /*****************************************************************************
821 * SetOffset: build offset array for conversion functions
822 *****************************************************************************
823 * This function will build an offset array used in later conversion functions.
824 * It will also set horizontal and vertical scaling indicators.
825 *****************************************************************************/
826 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
827 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
829 int i_x; /* x position in destination */
830 int i_scale_count; /* modulo counter */
833 * Prepare horizontal offset array
835 if( i_pic_width - i_width > 0 )
837 /* Prepare scaling array for horizontal extension */
839 i_scale_count = i_pic_width;
840 for( i_x = i_width; i_x--; )
842 while( (i_scale_count -= i_width) > 0 )
847 i_scale_count += i_pic_width;
850 else if( i_pic_width - i_width < 0 )
852 /* Prepare scaling array for horizontal reduction */
854 i_scale_count = i_pic_width;
855 for( i_x = i_pic_width; i_x--; )
858 while( (i_scale_count -= i_pic_width) >= 0 )
863 i_scale_count += i_width;
868 /* No horizontal scaling: YUV conversion is done directly to picture */
873 * Set vertical scaling indicator
875 if( i_pic_height - i_height > 0 )
879 else if( i_pic_height - i_height < 0 )
889 /*****************************************************************************
890 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
891 *****************************************************************************/
892 static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
893 yuv_data_t *p_u, yuv_data_t *p_v, int i_width,
894 int i_height, int i_pic_width, int i_pic_height,
895 int i_pic_line_width, int i_matrix_coefficients )
897 boolean_t b_horizontal_scaling; /* horizontal scaling type */
898 int i_vertical_scaling; /* vertical scaling type */
899 int i_x, i_y; /* horizontal and vertical indexes */
900 int i_scale_count; /* scale modulo counter */
901 int i_chroma_width; /* chroma width, not used */
902 u8 * p_gray; /* base conversion table */
903 u8 * p_pic_start; /* beginning of the current line for copy */
904 u8 * p_buffer_start; /* conversion buffer start */
905 u8 * p_buffer; /* conversion buffer pointer */
906 int * p_offset_start; /* offset array start */
907 int * p_offset; /* offset array pointer */
910 * Initialize some values - i_pic_line_width will store the line skip
912 i_pic_line_width -= i_pic_width;
913 p_gray = p_vout->yuv.yuv.p_gray8;
914 p_buffer_start = p_vout->yuv.p_buffer;
915 p_offset_start = p_vout->yuv.p_offset;
916 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
917 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
922 i_scale_count = i_pic_height;
923 for( i_y = 0; i_y < i_height; i_y++ )
925 /* Mark beginnning of line for possible later line copy, and initialize
928 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
930 /* Do YUV conversion to buffer - YUV picture is always formed of 16
931 * pixels wide blocks */
932 for( i_x = i_width / 16; i_x--; )
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++ ];
937 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
938 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
939 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
940 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
941 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
944 /* Do horizontal and vertical scaling */
946 SCALE_HEIGHT(400, 1);
950 /*****************************************************************************
951 * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
952 *****************************************************************************/
953 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,
954 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
955 int i_matrix_coefficients )
957 boolean_t b_horizontal_scaling; /* horizontal scaling type */
958 int i_vertical_scaling; /* vertical scaling type */
959 int i_x, i_y; /* horizontal and vertical indexes */
960 int i_scale_count; /* scale modulo counter */
961 int i_chroma_width; /* chroma width, not used */
962 u16 * p_gray; /* base conversion table */
963 u16 * p_pic_start; /* beginning of the current line for copy */
964 u16 * p_buffer_start; /* conversion buffer start */
965 u16 * p_buffer; /* conversion buffer pointer */
966 int * p_offset_start; /* offset array start */
967 int * p_offset; /* offset array pointer */
970 * Initialize some values - i_pic_line_width will store the line skip
972 i_pic_line_width -= i_pic_width;
973 p_gray = p_vout->yuv.yuv.p_gray16;
974 p_buffer_start = p_vout->yuv.p_buffer;
975 p_offset_start = p_vout->yuv.p_offset;
976 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
977 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
982 i_scale_count = i_pic_height;
983 for( i_y = 0; i_y < i_height; i_y++ )
985 /* Mark beginnning of line for possible later line copy, and initialize
988 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
990 /* Do YUV conversion to buffer - YUV picture is always formed of 16
991 * pixels wide blocks */
992 for( i_x = i_width / 16; i_x--; )
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++ ];
997 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
998 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
999 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1000 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1001 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1004 /* Do horizontal and vertical scaling */
1006 SCALE_HEIGHT(400, 2);
1010 /*****************************************************************************
1011 * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 3 Bpp
1012 *****************************************************************************/
1013 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,
1014 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1015 int i_matrix_coefficients )
1020 /*****************************************************************************
1021 * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
1022 *****************************************************************************/
1023 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,
1024 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1025 int i_matrix_coefficients )
1027 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1028 int i_vertical_scaling; /* vertical scaling type */
1029 int i_x, i_y; /* horizontal and vertical indexes */
1030 int i_scale_count; /* scale modulo counter */
1031 int i_chroma_width; /* chroma width, not used */
1032 u32 * p_gray; /* base conversion table */
1033 u32 * p_pic_start; /* beginning of the current line for copy */
1034 u32 * p_buffer_start; /* conversion buffer start */
1035 u32 * p_buffer; /* conversion buffer pointer */
1036 int * p_offset_start; /* offset array start */
1037 int * p_offset; /* offset array pointer */
1040 * Initialize some values - i_pic_line_width will store the line skip
1042 i_pic_line_width -= i_pic_width;
1043 p_gray = p_vout->yuv.yuv.p_gray32;
1044 p_buffer_start = p_vout->yuv.p_buffer;
1045 p_offset_start = p_vout->yuv.p_offset;
1046 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1047 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1050 * Perform conversion
1052 i_scale_count = i_pic_height;
1053 for( i_y = 0; i_y < i_height; i_y++ )
1055 /* Mark beginnning of line for possible later line copy, and initialize
1057 p_pic_start = p_pic;
1058 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1060 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1061 * pixels wide blocks */
1062 for( i_x = i_width / 16; i_x--; )
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++ ];
1067 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1068 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1069 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1070 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1071 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
1074 /* Do horizontal and vertical scaling */
1076 SCALE_HEIGHT(400, 4);
1080 /*****************************************************************************
1081 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
1082 *****************************************************************************/
1083 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,
1084 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1085 int i_matrix_coefficients )
1087 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1088 int i_vertical_scaling; /* vertical scaling type */
1089 int i_x, i_y; /* horizontal and vertical indexes */
1090 int i_scale_count; /* scale modulo counter */
1091 int b_jump_uv; /* should we jump u and v ? */
1092 int i_real_y; /* y % 4 */
1093 u8 * p_lookup; /* lookup table */
1094 int i_chroma_width; /* chroma width */
1095 int * p_offset_start; /* offset array start */
1096 int * p_offset; /* offset array pointer */
1099 int dither10[4] = { 0x7, 0x8, 0x7, 0x8 };
1100 int dither11[4] = { 0x8, 0x7, 0x8, 0x7 };
1101 int dither12[4] = { 0x7, 0x8, 0x7, 0x8 };
1102 int dither13[4] = { 0x8, 0x7, 0x8, 0x7 };
1104 int dither20[4] = { 0xf, 0x10, 0xf, 0x10 };
1105 int dither21[4] = { 0x10, 0xf, 0x10, 0xf };
1106 int dither22[4] = { 0xf, 0x10, 0xf, 0x10 };
1107 int dither23[4] = { 0x10, 0xf, 0x10, 0xf };
1109 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
1110 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
1111 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
1112 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
1114 int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
1115 int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
1116 int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
1117 int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
1120 /* some other matrices that can be interesting, either for debugging
1123 * { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} }
1124 * { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } }
1125 * { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } }
1126 * { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } }
1127 * { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } }
1128 * { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } }
1132 * Initialize some values - i_pic_line_width will store the line skip
1134 i_pic_line_width -= i_pic_width;
1135 i_chroma_width = i_width / 2;
1136 p_offset_start = p_vout->yuv.p_offset;
1137 p_lookup = p_vout->yuv.p_base;
1138 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1139 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1142 * Perform conversion
1144 i_scale_count = i_pic_height;
1146 for( i_y = 0; i_y < i_height; i_y++ )
1148 /* Do horizontal and vertical scaling */
1149 SCALE_WIDTH_DITHER( 420 );
1150 SCALE_HEIGHT_DITHER( 420 );
1154 /*****************************************************************************
1155 * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1156 *****************************************************************************/
1157 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,
1158 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1159 int i_matrix_coefficients )
1161 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1162 int i_vertical_scaling; /* vertical scaling type */
1163 int i_x, i_y; /* horizontal and vertical indexes */
1164 int i_scale_count; /* scale modulo counter */
1165 int i_uval, i_vval; /* U and V samples */
1166 int i_red, i_green, i_blue; /* U and V modified samples */
1167 int i_chroma_width; /* chroma width */
1168 u8 * p_yuv; /* base conversion table */
1169 u8 * p_ybase; /* Y dependant conversion table */
1170 u8 * p_pic_start; /* beginning of the current line for copy */
1171 u8 * p_buffer_start; /* conversion buffer start */
1172 u8 * p_buffer; /* conversion buffer pointer */
1173 int * p_offset_start; /* offset array start */
1174 int * p_offset; /* offset array pointer */
1177 * Initialize some values - i_pic_line_width will store the line skip
1179 i_pic_line_width -= i_pic_width;
1180 i_chroma_width = i_width / 2;
1181 p_yuv = p_vout->yuv.yuv.p_rgb8;
1182 p_buffer_start = p_vout->yuv.p_buffer;
1183 p_offset_start = p_vout->yuv.p_offset;
1184 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1185 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1188 * Perform conversion
1190 i_scale_count = i_pic_height;
1191 for( i_y = 0; i_y < i_height; i_y++ )
1193 /* Mark beginnning of line for possible later line copy, and initialize
1195 p_pic_start = p_pic;
1196 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1198 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1199 * pixels wide blocks */
1200 for( i_x = i_width / 16; i_x--; )
1202 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1203 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1204 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1205 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1206 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1207 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1208 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1209 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1212 /* Do horizontal and vertical scaling */
1214 SCALE_HEIGHT(422, 1);
1218 /*****************************************************************************
1219 * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1220 *****************************************************************************/
1221 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,
1222 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1223 int i_matrix_coefficients )
1225 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1226 int i_vertical_scaling; /* vertical scaling type */
1227 int i_x, i_y; /* horizontal and vertical indexes */
1228 int i_scale_count; /* scale modulo counter */
1229 int i_uval, i_vval; /* U and V samples */
1230 int i_red, i_green, i_blue; /* U and V modified samples */
1231 int i_chroma_width; /* chroma width, not used */
1232 u8 * p_yuv; /* base conversion table */
1233 u8 * p_ybase; /* Y dependant conversion table */
1234 u8 * p_pic_start; /* beginning of the current line for copy */
1235 u8 * p_buffer_start; /* conversion buffer start */
1236 u8 * p_buffer; /* conversion buffer pointer */
1237 int * p_offset_start; /* offset array start */
1238 int * p_offset; /* offset array pointer */
1241 * Initialize some values - i_pic_line_width will store the line skip
1243 i_pic_line_width -= i_pic_width;
1244 p_yuv = p_vout->yuv.yuv.p_rgb8;
1245 p_buffer_start = p_vout->yuv.p_buffer;
1246 p_offset_start = p_vout->yuv.p_offset;
1247 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1248 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1251 * Perform conversion
1253 i_scale_count = i_pic_height;
1254 for( i_y = 0; i_y < i_height; i_y++ )
1256 /* Mark beginnning of line for possible later line copy, and initialize
1258 p_pic_start = p_pic;
1259 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1261 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1262 * pixels wide blocks */
1263 for( i_x = i_width / 16; i_x--; )
1265 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1266 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1267 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1268 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1269 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1270 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1271 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1272 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1275 /* Do horizontal and vertical scaling */
1277 SCALE_HEIGHT(444, 1);
1281 /*****************************************************************************
1282 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1283 *****************************************************************************/
1284 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,
1285 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1286 int i_matrix_coefficients )
1290 int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
1292 i_chroma_width = i_width / 2;
1293 i_chroma_skip = i_skip / 2;
1294 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1295 (i_width + i_skip) * sizeof( yuv_data_t ),
1296 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1297 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1298 p_vout->i_screen_depth == 15 );
1300 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1301 int i_vertical_scaling; /* vertical scaling type */
1302 int i_x, i_y; /* horizontal and vertical indexes */
1303 int i_scale_count; /* scale modulo counter */
1304 int i_uval, i_vval; /* U and V samples */
1305 int i_red, i_green, i_blue; /* U and V modified samples */
1306 int i_chroma_width; /* chroma width */
1307 u16 * p_yuv; /* base conversion table */
1308 u16 * p_ybase; /* Y dependant conversion table */
1309 u16 * p_pic_start; /* beginning of the current line for copy */
1310 u16 * p_buffer_start; /* conversion buffer start */
1311 u16 * p_buffer; /* conversion buffer pointer */
1312 int * p_offset_start; /* offset array start */
1313 int * p_offset; /* offset array pointer */
1316 * Initialize some values - i_pic_line_width will store the line skip
1318 i_pic_line_width -= i_pic_width;
1319 i_chroma_width = i_width / 2;
1320 p_yuv = p_vout->yuv.yuv.p_rgb16;
1321 p_buffer_start = p_vout->yuv.p_buffer;
1322 p_offset_start = p_vout->yuv.p_offset;
1323 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1324 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1327 * Perform conversion
1329 i_scale_count = i_pic_height;
1330 for( i_y = 0; i_y < i_height; i_y++ )
1332 /* Mark beginnning of line for possible later line copy, and initialize
1334 p_pic_start = p_pic;
1335 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1337 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1338 * pixels wide blocks */
1339 for( i_x = i_width / 16; i_x--; )
1341 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1342 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1343 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1344 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1345 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1346 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1347 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1348 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1351 /* Do horizontal and vertical scaling */
1353 SCALE_HEIGHT(420, 2);
1357 /*****************************************************************************
1358 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1359 *****************************************************************************/
1360 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,
1361 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1362 int i_matrix_coefficients )
1364 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1365 int i_vertical_scaling; /* vertical scaling type */
1366 int i_x, i_y; /* horizontal and vertical indexes */
1367 int i_scale_count; /* scale modulo counter */
1368 int i_uval, i_vval; /* U and V samples */
1369 int i_red, i_green, i_blue; /* U and V modified samples */
1370 int i_chroma_width; /* chroma width */
1371 u16 * p_yuv; /* base conversion table */
1372 u16 * p_ybase; /* Y dependant conversion table */
1373 u16 * p_pic_start; /* beginning of the current line for copy */
1374 u16 * p_buffer_start; /* conversion buffer start */
1375 u16 * p_buffer; /* conversion buffer pointer */
1376 int * p_offset_start; /* offset array start */
1377 int * p_offset; /* offset array pointer */
1380 * Initialize some values - i_pic_line_width will store the line skip
1382 i_pic_line_width -= i_pic_width;
1383 i_chroma_width = i_width / 2;
1384 p_yuv = p_vout->yuv.yuv.p_rgb16;
1385 p_buffer_start = p_vout->yuv.p_buffer;
1386 p_offset_start = p_vout->yuv.p_offset;
1387 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1388 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1391 * Perform conversion
1393 i_scale_count = i_pic_height;
1394 for( i_y = 0; i_y < i_height; i_y++ )
1396 /* Mark beginnning of line for possible later line copy, and initialize
1398 p_pic_start = p_pic;
1399 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1401 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1402 * pixels wide blocks */
1403 for( i_x = i_width / 16; i_x--; )
1405 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1406 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1407 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1408 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1409 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1410 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1411 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1412 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1415 /* Do horizontal and vertical scaling */
1417 SCALE_HEIGHT(422, 2);
1421 /*****************************************************************************
1422 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1423 *****************************************************************************/
1424 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,
1425 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1426 int i_matrix_coefficients )
1428 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1429 int i_vertical_scaling; /* vertical scaling type */
1430 int i_x, i_y; /* horizontal and vertical indexes */
1431 int i_scale_count; /* scale modulo counter */
1432 int i_uval, i_vval; /* U and V samples */
1433 int i_red, i_green, i_blue; /* U and V modified samples */
1434 int i_chroma_width; /* chroma width, not used */
1435 u16 * p_yuv; /* base conversion table */
1436 u16 * p_ybase; /* Y dependant conversion table */
1437 u16 * p_pic_start; /* beginning of the current line for copy */
1438 u16 * p_buffer_start; /* conversion buffer start */
1439 u16 * p_buffer; /* conversion buffer pointer */
1440 int * p_offset_start; /* offset array start */
1441 int * p_offset; /* offset array pointer */
1444 * Initialize some values - i_pic_line_width will store the line skip
1446 i_pic_line_width -= i_pic_width;
1447 p_yuv = p_vout->yuv.yuv.p_rgb16;
1448 p_buffer_start = p_vout->yuv.p_buffer;
1449 p_offset_start = p_vout->yuv.p_offset;
1450 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1451 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1454 * Perform conversion
1456 i_scale_count = i_pic_height;
1457 for( i_y = 0; i_y < i_height; i_y++ )
1459 /* Mark beginnning of line for possible later line copy, and initialize
1461 p_pic_start = p_pic;
1462 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1464 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1465 * pixels wide blocks */
1466 for( i_x = i_width / 16; i_x--; )
1468 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1469 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1470 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1471 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1472 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1473 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1474 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1475 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1478 /* Do horizontal and vertical scaling */
1480 SCALE_HEIGHT(444, 2);
1484 /*****************************************************************************
1485 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1486 *****************************************************************************/
1487 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,
1488 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1489 int i_matrix_coefficients )
1494 /*****************************************************************************
1495 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1496 *****************************************************************************/
1497 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,
1498 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1499 int i_matrix_coefficients )
1504 /*****************************************************************************
1505 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1506 *****************************************************************************/
1507 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,
1508 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1509 int i_matrix_coefficients )
1514 /*****************************************************************************
1515 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1516 *****************************************************************************/
1517 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,
1518 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1519 int i_matrix_coefficients )
1521 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1522 int i_vertical_scaling; /* vertical scaling type */
1523 int i_x, i_y; /* horizontal and vertical indexes */
1524 int i_scale_count; /* scale modulo counter */
1525 int i_uval, i_vval; /* U and V samples */
1526 int i_red, i_green, i_blue; /* U and V modified samples */
1527 int i_chroma_width; /* chroma width */
1528 u32 * p_yuv; /* base conversion table */
1529 u32 * p_ybase; /* Y dependant conversion table */
1530 u32 * p_pic_start; /* beginning of the current line for copy */
1531 u32 * p_buffer_start; /* conversion buffer start */
1532 u32 * p_buffer; /* conversion buffer pointer */
1533 int * p_offset_start; /* offset array start */
1534 int * p_offset; /* offset array pointer */
1537 * Initialize some values - i_pic_line_width will store the line skip
1539 i_pic_line_width -= i_pic_width;
1540 i_chroma_width = i_width / 2;
1541 p_yuv = p_vout->yuv.yuv.p_rgb32;
1542 p_buffer_start = p_vout->yuv.p_buffer;
1543 p_offset_start = p_vout->yuv.p_offset;
1544 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1545 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1548 * Perform conversion
1550 i_scale_count = i_pic_height;
1551 for( i_y = 0; i_y < i_height; i_y++ )
1553 /* Mark beginnning of line for possible later line copy, and initialize
1555 p_pic_start = p_pic;
1556 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1558 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1559 * pixels wide blocks */
1560 for( i_x = i_width / 16; i_x--; )
1562 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1563 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1564 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1565 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1566 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1567 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1568 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1569 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1572 /* Do horizontal and vertical scaling */
1574 SCALE_HEIGHT(420, 4);
1578 /*****************************************************************************
1579 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1580 *****************************************************************************/
1581 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,
1582 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1583 int i_matrix_coefficients )
1585 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1586 int i_vertical_scaling; /* vertical scaling type */
1587 int i_x, i_y; /* horizontal and vertical indexes */
1588 int i_scale_count; /* scale modulo counter */
1589 int i_uval, i_vval; /* U and V samples */
1590 int i_red, i_green, i_blue; /* U and V modified samples */
1591 int i_chroma_width; /* chroma width */
1592 u32 * p_yuv; /* base conversion table */
1593 u32 * p_ybase; /* Y dependant conversion table */
1594 u32 * p_pic_start; /* beginning of the current line for copy */
1595 u32 * p_buffer_start; /* conversion buffer start */
1596 u32 * p_buffer; /* conversion buffer pointer */
1597 int * p_offset_start; /* offset array start */
1598 int * p_offset; /* offset array pointer */
1601 * Initialize some values - i_pic_line_width will store the line skip
1603 i_pic_line_width -= i_pic_width;
1604 i_chroma_width = i_width / 2;
1605 p_yuv = p_vout->yuv.yuv.p_rgb32;
1606 p_buffer_start = p_vout->yuv.p_buffer;
1607 p_offset_start = p_vout->yuv.p_offset;
1608 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1609 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1612 * Perform conversion
1614 i_scale_count = i_pic_height;
1615 for( i_y = 0; i_y < i_height; i_y++ )
1617 /* Mark beginnning of line for possible later line copy, and initialize
1619 p_pic_start = p_pic;
1620 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1622 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1623 * pixels wide blocks */
1624 for( i_x = i_width / 16; i_x--; )
1626 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1627 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1628 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1629 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1630 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1631 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1632 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1633 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1636 /* Do horizontal and vertical scaling */
1638 SCALE_HEIGHT(422, 4);
1642 /*****************************************************************************
1643 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1644 *****************************************************************************/
1645 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,
1646 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1647 int i_matrix_coefficients )
1649 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1650 int i_vertical_scaling; /* vertical scaling type */
1651 int i_x, i_y; /* horizontal and vertical indexes */
1652 int i_scale_count; /* scale modulo counter */
1653 int i_uval, i_vval; /* U and V samples */
1654 int i_red, i_green, i_blue; /* U and V modified samples */
1655 int i_chroma_width; /* chroma width, not used */
1656 u32 * p_yuv; /* base conversion table */
1657 u32 * p_ybase; /* Y dependant conversion table */
1658 u32 * p_pic_start; /* beginning of the current line for copy */
1659 u32 * p_buffer_start; /* conversion buffer start */
1660 u32 * p_buffer; /* conversion buffer pointer */
1661 int * p_offset_start; /* offset array start */
1662 int * p_offset; /* offset array pointer */
1665 * Initialize some values - i_pic_line_width will store the line skip
1667 i_pic_line_width -= i_pic_width;
1668 p_yuv = p_vout->yuv.yuv.p_rgb32;
1669 p_buffer_start = p_vout->yuv.p_buffer;
1670 p_offset_start = p_vout->yuv.p_offset;
1671 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1672 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1675 * Perform conversion
1677 i_scale_count = i_pic_height;
1678 for( i_y = 0; i_y < i_height; i_y++ )
1680 /* Mark beginnning of line for possible later line copy, and initialize
1682 p_pic_start = p_pic;
1683 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1685 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1686 * pixels wide blocks */
1687 for( i_x = i_width / 16; i_x--; )
1689 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1690 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1691 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1692 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1693 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1694 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1695 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1696 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1699 /* Do horizontal and vertical scaling */
1701 SCALE_HEIGHT(444, 4);
1705 /*-------------------- walken code follows ----------------------------------*/
1708 * YUV to RGB routines.
1710 * these routines calculate r, g and b values from each pixel's y, u and v.
1711 * these r, g an b values are then passed thru a table lookup to take the
1712 * gamma curve into account and find the corresponding pixel value.
1714 * the table must store more than 3*256 values because of the possibility
1715 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1716 * values are in the following intervals :
1717 * -176 to 255+176 for red
1718 * -133 to 255+133 for green
1719 * -222 to 255+222 for blue
1721 * If the input y,u,v values are right, the r,g,b results are not expected
1722 * to move out of the 0 to 255 interval but who knows what will happen in
1725 * the red, green and blue conversion tables are stored in a single 1935-entry
1726 * array. The respective positions of each component in the array have been
1727 * calculated to minimize the cache interactions of the 3 tables.
1732 static void yuvToRgb24 (unsigned char * Y,
1733 unsigned char * U, unsigned char * V,
1734 char * dest, int table[1935], int width)
1749 uvRed = (V_RED_COEF*v) >> SHIFT;
1750 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1751 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1753 tableY = table + *(Y++);
1754 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1755 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1757 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1759 *(dest++) = tmp24 >> 8;
1760 *(dest++) = tmp24 >> 16;
1762 tableY = table + *(Y++);
1763 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1764 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1766 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1768 *(dest++) = tmp24 >> 8;
1769 *(dest++) = tmp24 >> 16;
1773 uvRed = (V_RED_COEF*v) >> SHIFT;
1774 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1775 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1777 tableY = table + *(Y++);
1778 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1779 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1781 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1783 *(dest++) = tmp24 >> 8;
1784 *(dest++) = tmp24 >> 16;
1786 tableY = table + *(Y++);
1787 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1788 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1790 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1792 *(dest++) = tmp24 >> 8;
1793 *(dest++) = tmp24 >> 16;
1797 uvRed = (V_RED_COEF*v) >> SHIFT;
1798 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1799 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1801 tableY = table + *(Y++);
1802 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1803 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1805 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1807 *(dest++) = tmp24 >> 8;
1808 *(dest++) = tmp24 >> 16;
1810 tableY = table + *(Y++);
1811 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1812 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1814 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1816 *(dest++) = tmp24 >> 8;
1817 *(dest++) = tmp24 >> 16;
1821 uvRed = (V_RED_COEF*v) >> SHIFT;
1822 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1823 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1825 tableY = table + *(Y++);
1826 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1827 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1829 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1831 *(dest++) = tmp24 >> 8;
1832 *(dest++) = tmp24 >> 16;
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;
1844 i = (width & 7) >> 1;
1848 uvRed = (V_RED_COEF*v) >> SHIFT;
1849 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1850 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1852 tableY = table + *(Y++);
1853 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1854 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1856 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1858 *(dest++) = tmp24 >> 8;
1859 *(dest++) = tmp24 >> 16;
1861 tableY = table + *(Y++);
1862 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1863 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1865 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1867 *(dest++) = tmp24 >> 8;
1868 *(dest++) = tmp24 >> 16;
1874 uvRed = (V_RED_COEF*v) >> SHIFT;
1875 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1876 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1878 tableY = table + *(Y++);
1879 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1880 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1882 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1884 *(dest++) = tmp24 >> 8;
1885 *(dest++) = tmp24 >> 16;