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))
76 /*****************************************************************************
78 *****************************************************************************/
79 static void SetGammaTable ( int *pi_table, double f_gamma );
80 static void SetYUV ( vout_thread_t *p_vout );
81 static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height,
82 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );
84 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 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,
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 );
129 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,
130 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
131 int i_matrix_coefficients );
133 /*****************************************************************************
134 * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel conversion blocks
135 *****************************************************************************
136 * These conversion routines are used by YUV conversion functions.
137 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
138 * which is also modified.
139 *****************************************************************************/
140 #define CONVERT_Y_PIXEL( BPP ) \
141 /* Only Y sample is present */ \
142 p_ybase = p_yuv + *p_y++; \
143 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
144 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
145 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
147 #define CONVERT_YUV_PIXEL( BPP ) \
148 /* Y, U and V samples are present */ \
151 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
152 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
153 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
154 CONVERT_Y_PIXEL( BPP ) \
156 /*****************************************************************************
157 * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp
158 *****************************************************************************
159 * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
160 *****************************************************************************/
161 #define CONVERT_4YUV_PIXELS( CHROMA ) \
162 *p_pic++ = p_lookup[ \
163 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
164 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
165 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
166 *p_pic++ = p_lookup[ \
167 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
168 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
169 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
170 *p_pic++ = p_lookup[ \
171 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
172 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
173 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
174 *p_pic++ = p_lookup[ \
175 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
176 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
177 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
179 #define CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
180 *p_pic++ = p_lookup[ \
181 (((*p_y + dither10[i_real_y]) >> 4) << 7) \
182 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
183 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
184 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
186 p_u += *p_offset & b_jump_uv; \
187 p_v += *p_offset++ & b_jump_uv; \
188 *p_pic++ = p_lookup[ \
189 (((*p_y + dither11[i_real_y]) >> 4) << 7) \
190 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
191 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
192 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
194 p_u += *p_offset & b_jump_uv; \
195 p_v += *p_offset++ & b_jump_uv; \
196 *p_pic++ = p_lookup[ \
197 (((*p_y + dither12[i_real_y]) >> 4) << 7) \
198 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
199 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
200 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
202 p_u += *p_offset & b_jump_uv; \
203 p_v += *p_offset++ & b_jump_uv; \
204 *p_pic++ = p_lookup[ \
205 (((*p_y + dither13[i_real_y]) >> 4) << 7) \
206 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
207 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
208 b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \
210 p_u += *p_offset & b_jump_uv; \
211 p_v += *p_offset++ & b_jump_uv; \
213 /*****************************************************************************
214 * SCALE_WIDTH: scale a line horizontally
215 *****************************************************************************
216 * This macro scales a line using rendering buffer and offset array. It works
217 * for 1, 2 and 4 Bpp.
218 *****************************************************************************/
219 #define SCALE_WIDTH \
220 if( b_horizontal_scaling ) \
222 /* Horizontal scaling, conversion has been done to buffer. \
223 * Rewind buffer and offset, then copy and scale line */ \
224 p_buffer = p_buffer_start; \
225 p_offset = p_offset_start; \
226 for( i_x = i_pic_width / 16; i_x--; ) \
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++; \
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++; \
245 p_pic += i_pic_line_width; \
249 /* No scaling, conversion has been done directly in picture memory. \
250 * Increment of picture pointer to end of line is still needed */ \
251 p_pic += i_pic_width + i_pic_line_width; \
255 /*****************************************************************************
256 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
257 *****************************************************************************
258 * This macro scales a line using an offset array.
259 *****************************************************************************/
260 #define SCALE_WIDTH_DITHER( CHROMA ) \
261 if( b_horizontal_scaling ) \
263 /* Horizontal scaling, but we can't use a buffer due to dither */ \
264 p_offset = p_offset_start; \
266 for( i_x = i_pic_width / 16; i_x--; ) \
268 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
269 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
270 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
271 CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \
276 for( i_x = i_width / 16; i_x--; ) \
278 CONVERT_4YUV_PIXELS( CHROMA ) \
279 CONVERT_4YUV_PIXELS( CHROMA ) \
280 CONVERT_4YUV_PIXELS( CHROMA ) \
281 CONVERT_4YUV_PIXELS( CHROMA ) \
284 /* Increment of picture pointer to end of line is still needed */ \
285 p_pic += i_pic_line_width; \
286 i_real_y = (i_real_y + 1) & 0x3; \
288 /*****************************************************************************
289 * SCALE_HEIGHT: handle vertical scaling
290 *****************************************************************************
291 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
292 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
294 *****************************************************************************/
295 #define SCALE_HEIGHT( CHROMA, BPP ) \
296 /* If line is odd, rewind 4:2:0 U and V samples */ \
297 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
299 p_u -= i_chroma_width; \
300 p_v -= i_chroma_width; \
304 * Handle vertical scaling. The current line can be copied or next one \
307 switch( i_vertical_scaling ) \
309 case -1: /* vertical scaling factor is < 1 */ \
310 while( (i_scale_count -= i_pic_height) >= 0 ) \
312 /* Height reduction: skip next source line */ \
315 if( (CHROMA == 420) || (CHROMA == 422) ) \
319 p_u += i_chroma_width; \
320 p_v += i_chroma_width; \
323 else if( CHROMA == 444 ) \
329 i_scale_count += i_height; \
331 case 1: /* vertical scaling factor is > 1 */ \
332 while( (i_scale_count -= i_height) > 0 ) \
334 /* Height increment: copy previous picture line */ \
335 for( i_x = i_pic_width / 16; i_x--; ) \
337 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
338 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
339 if( BPP > 1 ) /* 2, 3, 4 Bpp */ \
341 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
342 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
344 if( BPP > 2 ) /* 3, 4 Bpp */ \
346 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
347 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
349 if( BPP > 3 ) /* 4 Bpp */ \
351 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
352 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ ); \
355 p_pic += i_pic_line_width; \
356 p_pic_start += i_pic_line_width; \
358 i_scale_count += i_pic_height; \
362 /*****************************************************************************
363 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
364 *****************************************************************************
365 * This macro handles vertical scaling for a picture. CHROMA may be 420, 422 or
366 * 444 for RGB conversion, or 400 for gray conversion.
367 *****************************************************************************/
368 #define SCALE_HEIGHT_DITHER( CHROMA ) \
370 /* If line is odd, rewind 4:2:0 U and V samples */ \
371 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
373 p_u -= i_chroma_width; \
374 p_v -= i_chroma_width; \
378 * Handle vertical scaling. The current line can be copied or next one \
382 switch( i_vertical_scaling ) \
384 case -1: /* vertical scaling factor is < 1 */ \
385 while( (i_scale_count -= i_pic_height) >= 0 ) \
387 /* Height reduction: skip next source line */ \
390 if( (CHROMA == 420) || (CHROMA == 422) ) \
394 p_u += i_chroma_width; \
395 p_v += i_chroma_width; \
398 else if( CHROMA == 444 ) \
404 i_scale_count += i_height; \
406 case 1: /* vertical scaling factor is > 1 */ \
407 while( (i_scale_count -= i_height) > 0 ) \
409 SCALE_WIDTH_DITHER( CHROMA ); \
411 p_u -= i_chroma_width; \
412 p_v -= i_chroma_width; \
413 p_pic += i_pic_line_width; \
415 i_scale_count += i_pic_height; \
419 /*****************************************************************************
420 * vout_InitYUV: allocate and initialize translations tables
421 *****************************************************************************
422 * This function will allocate memory to store translation tables, depending
423 * of the screen depth.
424 *****************************************************************************/
425 int vout_InitYUV( vout_thread_t *p_vout )
427 size_t tables_size; /* tables size, in bytes */
429 /* Computes tables size - 3 Bpp use 32 bits pixel entries in tables */
430 switch( p_vout->i_bytes_per_pixel )
433 tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE);
436 tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
441 tables_size = sizeof( u32 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
445 /* Allocate memory */
446 p_vout->yuv.p_base = malloc( tables_size );
447 if( p_vout->yuv.p_base == NULL )
449 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
453 /* Allocate memory for conversion buffer and offset array */
454 p_vout->yuv.p_buffer = malloc( VOUT_MAX_WIDTH * p_vout->i_bytes_per_pixel );
455 if( p_vout->yuv.p_buffer == NULL )
457 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
458 free( p_vout->yuv.p_base );
461 p_vout->yuv.p_offset = malloc( p_vout->i_width * sizeof( int ) );
462 if( p_vout->yuv.p_offset == NULL )
464 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
465 free( p_vout->yuv.p_base );
466 free( p_vout->yuv.p_buffer );
470 /* Initialize tables */
475 /*****************************************************************************
476 * vout_ResetTables: re-initialize translations tables
477 *****************************************************************************
478 * This function will initialize the tables allocated by vout_CreateTables and
479 * set functions pointers.
480 *****************************************************************************/
481 int vout_ResetYUV( vout_thread_t *p_vout )
483 vout_EndYUV( p_vout );
484 return( vout_InitYUV( p_vout ) );
487 /*****************************************************************************
488 * vout_EndYUV: destroy translations tables
489 *****************************************************************************
490 * Free memory allocated by vout_CreateTables.
491 *****************************************************************************/
492 void vout_EndYUV( vout_thread_t *p_vout )
494 free( p_vout->yuv.p_base );
495 free( p_vout->yuv.p_buffer );
496 free( p_vout->yuv.p_offset );
499 /* following functions are local */
501 /*****************************************************************************
502 * SetGammaTable: return intensity table transformed by gamma curve.
503 *****************************************************************************
504 * pi_table is a table of 256 entries from 0 to 255.
505 *****************************************************************************/
506 static void SetGammaTable( int *pi_table, double f_gamma )
508 int i_y; /* base intensity */
510 /* Use exp(gamma) instead of gamma */
511 f_gamma = exp( f_gamma );
513 /* Build gamma table */
514 for( i_y = 0; i_y < 256; i_y++ )
516 pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
520 /*****************************************************************************
521 * SetYUV: compute tables and set function pointers
522 + *****************************************************************************/
523 static void SetYUV( vout_thread_t *p_vout )
525 int pi_gamma[256]; /* gamma table */
526 int i_index; /* index in tables */
528 /* Build gamma table */
529 SetGammaTable( pi_gamma, p_vout->f_gamma );
532 * Set pointers and build YUV tables
534 if( p_vout->b_grayscale )
536 /* Grayscale: build gray table */
537 switch( p_vout->i_bytes_per_pixel )
541 u16 bright[256], transp[256];
543 p_vout->yuv.yuv.p_gray8 = (u8 *)p_vout->yuv.p_base + GRAY_MARGIN;
544 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
546 p_vout->yuv.yuv.p_gray8[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
547 p_vout->yuv.yuv.p_gray8[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
549 for( i_index = 0; i_index < 256; i_index++)
551 p_vout->yuv.yuv.p_gray8[ i_index ] = pi_gamma[ i_index ];
552 bright[ i_index ] = i_index << 8;
553 transp[ i_index ] = 0;
555 /* the colors have been allocated, we can set the palette */
556 p_vout->p_set_palette( p_vout, bright, bright, bright, transp );
557 p_vout->i_white_pixel = 0xff;
558 p_vout->i_black_pixel = 0x00;
559 p_vout->i_gray_pixel = 0x44;
560 p_vout->i_blue_pixel = 0x3b;
565 p_vout->yuv.yuv.p_gray16 = (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
566 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
568 p_vout->yuv.yuv.p_gray16[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
569 p_vout->yuv.yuv.p_gray16[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
571 for( i_index = 0; i_index < 256; i_index++)
573 p_vout->yuv.yuv.p_gray16[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
578 p_vout->yuv.yuv.p_gray32 = (u32 *)p_vout->yuv.p_base + GRAY_MARGIN;
579 for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
581 p_vout->yuv.yuv.p_gray32[ -i_index ] = RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
582 p_vout->yuv.yuv.p_gray32[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
584 for( i_index = 0; i_index < 256; i_index++)
586 p_vout->yuv.yuv.p_gray32[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
593 /* Color: build red, green and blue tables */
594 switch( p_vout->i_bytes_per_pixel )
600 #define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 )
606 u16 red[256], green[256], blue[256], transp[256];
607 unsigned char lookup[PALETTE_TABLE_SIZE];
609 p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
611 /* this loop calculates the intersection of an YUV box
612 * and the RGB cube. */
613 for ( y = 0; y <= 256; y += 16 )
615 for ( u = 0; u <= 256; u += 32 )
616 for ( v = 0; v <= 256; v += 32 )
618 uvr = (V_RED_COEF*(v-128)) >> SHIFT;
619 uvg = (U_GREEN_COEF*(u-128) + V_GREEN_COEF*(v-128)) >> SHIFT;
620 uvb = (U_BLUE_COEF*(u-128)) >> SHIFT;
625 if( r >= RGB_MIN && g >= RGB_MIN && b >= RGB_MIN
626 && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
628 /* this one should never happen unless someone fscked up my code */
629 if(j == 256) { intf_ErrMsg( "vout error: no colors left to build palette\n" ); break; }
631 /* clip the colors */
633 green[j] = CLIP( g );
639 p_vout->yuv.yuv.p_rgb8[i++] = j;
645 p_vout->yuv.yuv.p_rgb8[i++] = 0;
651 /* the colors have been allocated, we can set the palette */
652 /* there will eventually be a way to know which colors
653 * couldn't be allocated and try to find a replacement */
654 p_vout->p_set_palette( p_vout, red, green, blue, transp );
656 p_vout->i_white_pixel = 0xff;
657 p_vout->i_black_pixel = 0x00;
658 p_vout->i_gray_pixel = 0x44;
659 p_vout->i_blue_pixel = 0x3b;
662 /* this loop allocates colors that got outside
664 for ( y = 0; y <= 256; y += 16 )
666 for ( u = 0; u <= 256; u += 32 )
667 for ( v = 0; v <= 256; v += 32 )
670 int dist, mindist = 100000000;
672 if( lookup[i] || y==0)
679 for( u2 = 0; u2 <= 256; u2 += 32 )
680 for( v2 = 0; v2 <= 256; v2 += 32 )
682 j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
683 dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
685 /* find the nearest color */
688 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
693 /* find the nearest color */
694 if( dist + 128 < mindist )
696 p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
697 mindist = dist + 128;
708 p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
709 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
711 p_vout->yuv.yuv.p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
712 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
714 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
716 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
717 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
719 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
721 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
722 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
724 for( i_index = 0; i_index < 256; i_index++ )
726 p_vout->yuv.yuv.p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
727 p_vout->yuv.yuv.p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
728 p_vout->yuv.yuv.p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
733 p_vout->yuv.yuv.p_rgb32 = (u32 *)p_vout->yuv.p_base;
734 for( i_index = 0; i_index < RED_MARGIN; i_index++ )
736 p_vout->yuv.yuv.p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
737 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
739 for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
741 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
742 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
744 for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
746 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
747 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
749 for( i_index = 0; i_index < 256; i_index++ )
751 p_vout->yuv.yuv.p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
752 p_vout->yuv.yuv.p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
753 p_vout->yuv.yuv.p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
760 * Set functions pointers
762 if( p_vout->b_grayscale )
765 switch( p_vout->i_bytes_per_pixel )
768 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray8;
769 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray8;
770 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray8;
773 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray16;
774 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray16;
775 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray16;
778 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray24;
779 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray24;
780 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray24;
783 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertY4Gray32;
784 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertY4Gray32;
785 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertY4Gray32;
792 switch( p_vout->i_bytes_per_pixel )
795 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB8;
796 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB8;
797 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB8;
800 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB16;
801 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB16;
802 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB16;
805 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB24;
806 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB24;
807 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB24;
810 p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertYUV420RGB32;
811 p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertYUV422RGB32;
812 p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertYUV444RGB32;
818 /*****************************************************************************
819 * SetOffset: build offset array for conversion functions
820 *****************************************************************************
821 * This function will build an offset array used in later conversion functions.
822 * It will also set horizontal and vertical scaling indicators.
823 *****************************************************************************/
824 static void SetOffset( int i_width, int i_height, int i_pic_width, int i_pic_height,
825 boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset )
827 int i_x; /* x position in destination */
828 int i_scale_count; /* modulo counter */
831 * Prepare horizontal offset array
833 if( i_pic_width - i_width > 0 )
835 /* Prepare scaling array for horizontal extension */
837 i_scale_count = i_pic_width;
838 for( i_x = i_width; i_x--; )
840 while( (i_scale_count -= i_width) > 0 )
845 i_scale_count += i_pic_width;
848 else if( i_pic_width - i_width < 0 )
850 /* Prepare scaling array for horizontal reduction */
852 i_scale_count = i_pic_width;
853 for( i_x = i_pic_width; i_x--; )
856 while( (i_scale_count -= i_pic_width) >= 0 )
861 i_scale_count += i_width;
866 /* No horizontal scaling: YUV conversion is done directly to picture */
871 * Set vertical scaling indicator
873 if( i_pic_height - i_height > 0 )
877 else if( i_pic_height - i_height < 0 )
887 /*****************************************************************************
888 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
889 *****************************************************************************/
890 static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
891 yuv_data_t *p_u, yuv_data_t *p_v, int i_width,
892 int i_height, int i_pic_width, int i_pic_height,
893 int i_pic_line_width, int i_matrix_coefficients )
895 boolean_t b_horizontal_scaling; /* horizontal scaling type */
896 int i_vertical_scaling; /* vertical scaling type */
897 int i_x, i_y; /* horizontal and vertical indexes */
898 int i_scale_count; /* scale modulo counter */
899 int i_chroma_width; /* chroma width, not used */
900 u8 * p_gray; /* base conversion table */
901 u8 * p_pic_start; /* beginning of the current line for copy */
902 u8 * p_buffer_start; /* conversion buffer start */
903 u8 * p_buffer; /* conversion buffer pointer */
904 int * p_offset_start; /* offset array start */
905 int * p_offset; /* offset array pointer */
908 * Initialize some values - i_pic_line_width will store the line skip
910 i_pic_line_width -= i_pic_width;
911 p_gray = p_vout->yuv.yuv.p_gray8;
912 p_buffer_start = p_vout->yuv.p_buffer;
913 p_offset_start = p_vout->yuv.p_offset;
914 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
915 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
920 i_scale_count = i_pic_height;
921 for( i_y = 0; i_y < i_height; i_y++ )
923 /* Mark beginnning of line for possible later line copy, and initialize
926 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
928 /* Do YUV conversion to buffer - YUV picture is always formed of 16
929 * pixels wide blocks */
930 for( i_x = i_width / 16; i_x--; )
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++ ];
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++ ];
942 /* Do horizontal and vertical scaling */
944 SCALE_HEIGHT(400, 1);
948 /*****************************************************************************
949 * ConvertY4Gray16: grayscale YUV 4:x:x to RGB 2 Bpp
950 *****************************************************************************/
951 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,
952 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
953 int i_matrix_coefficients )
955 boolean_t b_horizontal_scaling; /* horizontal scaling type */
956 int i_vertical_scaling; /* vertical scaling type */
957 int i_x, i_y; /* horizontal and vertical indexes */
958 int i_scale_count; /* scale modulo counter */
959 int i_chroma_width; /* chroma width, not used */
960 u16 * p_gray; /* base conversion table */
961 u16 * p_pic_start; /* beginning of the current line for copy */
962 u16 * p_buffer_start; /* conversion buffer start */
963 u16 * p_buffer; /* conversion buffer pointer */
964 int * p_offset_start; /* offset array start */
965 int * p_offset; /* offset array pointer */
968 * Initialize some values - i_pic_line_width will store the line skip
970 i_pic_line_width -= i_pic_width;
971 p_gray = p_vout->yuv.yuv.p_gray16;
972 p_buffer_start = p_vout->yuv.p_buffer;
973 p_offset_start = p_vout->yuv.p_offset;
974 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
975 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
980 i_scale_count = i_pic_height;
981 for( i_y = 0; i_y < i_height; i_y++ )
983 /* Mark beginnning of line for possible later line copy, and initialize
986 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
988 /* Do YUV conversion to buffer - YUV picture is always formed of 16
989 * pixels wide blocks */
990 for( i_x = i_width / 16; i_x--; )
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++ ];
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++ ];
1002 /* Do horizontal and vertical scaling */
1004 SCALE_HEIGHT(400, 2);
1008 /*****************************************************************************
1009 * ConvertY4Gray24: grayscale YUV 4:x:x to RGB 3 Bpp
1010 *****************************************************************************/
1011 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,
1012 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1013 int i_matrix_coefficients )
1018 /*****************************************************************************
1019 * ConvertY4Gray32: grayscale YUV 4:x:x to RGB 4 Bpp
1020 *****************************************************************************/
1021 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,
1022 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1023 int i_matrix_coefficients )
1025 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1026 int i_vertical_scaling; /* vertical scaling type */
1027 int i_x, i_y; /* horizontal and vertical indexes */
1028 int i_scale_count; /* scale modulo counter */
1029 int i_chroma_width; /* chroma width, not used */
1030 u32 * p_gray; /* base conversion table */
1031 u32 * p_pic_start; /* beginning of the current line for copy */
1032 u32 * p_buffer_start; /* conversion buffer start */
1033 u32 * p_buffer; /* conversion buffer pointer */
1034 int * p_offset_start; /* offset array start */
1035 int * p_offset; /* offset array pointer */
1038 * Initialize some values - i_pic_line_width will store the line skip
1040 i_pic_line_width -= i_pic_width;
1041 p_gray = p_vout->yuv.yuv.p_gray32;
1042 p_buffer_start = p_vout->yuv.p_buffer;
1043 p_offset_start = p_vout->yuv.p_offset;
1044 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1045 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1048 * Perform conversion
1050 i_scale_count = i_pic_height;
1051 for( i_y = 0; i_y < i_height; i_y++ )
1053 /* Mark beginnning of line for possible later line copy, and initialize
1055 p_pic_start = p_pic;
1056 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1058 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1059 * pixels wide blocks */
1060 for( i_x = i_width / 16; i_x--; )
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++ ];
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++ ];
1072 /* Do horizontal and vertical scaling */
1074 SCALE_HEIGHT(400, 4);
1078 /*****************************************************************************
1079 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
1080 *****************************************************************************/
1081 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,
1082 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1083 int i_matrix_coefficients )
1085 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1086 int i_vertical_scaling; /* vertical scaling type */
1087 int i_x, i_y; /* horizontal and vertical indexes */
1088 int i_scale_count; /* scale modulo counter */
1089 int b_jump_uv; /* should we jump u and v ? */
1090 int i_real_y; /* y % 4 */
1091 u8 * p_lookup; /* lookup table */
1092 int i_chroma_width; /* chroma width */
1093 int * p_offset_start; /* offset array start */
1094 int * p_offset; /* offset array pointer */
1096 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
1097 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
1098 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
1099 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
1101 int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
1102 int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
1103 int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
1104 int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
1106 /* other matrices that can be interesting, either for debugging or for effects */
1108 int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
1109 int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
1110 int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
1111 int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
1112 int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
1113 int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
1117 * Initialize some values - i_pic_line_width will store the line skip
1119 i_pic_line_width -= i_pic_width;
1120 i_chroma_width = i_width / 2;
1121 p_offset_start = p_vout->yuv.p_offset;
1122 p_lookup = p_vout->yuv.p_base;
1123 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1124 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1127 * Perform conversion
1129 i_scale_count = i_pic_height;
1131 for( i_y = 0; i_y < i_height; i_y++ )
1133 /* Do horizontal and vertical scaling */
1134 SCALE_WIDTH_DITHER( 420 );
1135 SCALE_HEIGHT_DITHER( 420 );
1139 /*****************************************************************************
1140 * ConvertYUV422RGB8: color YUV 4:2:2 to RGB 8 bpp
1141 *****************************************************************************/
1142 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,
1143 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1144 int i_matrix_coefficients )
1146 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1147 int i_vertical_scaling; /* vertical scaling type */
1148 int i_x, i_y; /* horizontal and vertical indexes */
1149 int i_scale_count; /* scale modulo counter */
1150 int i_uval, i_vval; /* U and V samples */
1151 int i_red, i_green, i_blue; /* U and V modified samples */
1152 int i_chroma_width; /* chroma width */
1153 u8 * p_yuv; /* base conversion table */
1154 u8 * p_ybase; /* Y dependant conversion table */
1155 u8 * p_pic_start; /* beginning of the current line for copy */
1156 u8 * p_buffer_start; /* conversion buffer start */
1157 u8 * p_buffer; /* conversion buffer pointer */
1158 int * p_offset_start; /* offset array start */
1159 int * p_offset; /* offset array pointer */
1162 * Initialize some values - i_pic_line_width will store the line skip
1164 i_pic_line_width -= i_pic_width;
1165 i_chroma_width = i_width / 2;
1166 p_yuv = p_vout->yuv.yuv.p_rgb8;
1167 p_buffer_start = p_vout->yuv.p_buffer;
1168 p_offset_start = p_vout->yuv.p_offset;
1169 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1170 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1173 * Perform conversion
1175 i_scale_count = i_pic_height;
1176 for( i_y = 0; i_y < i_height; i_y++ )
1178 /* Mark beginnning of line for possible later line copy, and initialize
1180 p_pic_start = p_pic;
1181 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1183 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1184 * pixels wide blocks */
1185 for( i_x = i_width / 16; i_x--; )
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);
1192 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1193 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1194 CONVERT_YUV_PIXEL(1); CONVERT_Y_PIXEL(1);
1197 /* Do horizontal and vertical scaling */
1199 SCALE_HEIGHT(422, 1);
1203 /*****************************************************************************
1204 * ConvertYUV444RGB8: color YUV 4:4:4 to RGB 8 bpp
1205 *****************************************************************************/
1206 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,
1207 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1208 int i_matrix_coefficients )
1210 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1211 int i_vertical_scaling; /* vertical scaling type */
1212 int i_x, i_y; /* horizontal and vertical indexes */
1213 int i_scale_count; /* scale modulo counter */
1214 int i_uval, i_vval; /* U and V samples */
1215 int i_red, i_green, i_blue; /* U and V modified samples */
1216 int i_chroma_width; /* chroma width, not used */
1217 u8 * p_yuv; /* base conversion table */
1218 u8 * p_ybase; /* Y dependant conversion table */
1219 u8 * p_pic_start; /* beginning of the current line for copy */
1220 u8 * p_buffer_start; /* conversion buffer start */
1221 u8 * p_buffer; /* conversion buffer pointer */
1222 int * p_offset_start; /* offset array start */
1223 int * p_offset; /* offset array pointer */
1226 * Initialize some values - i_pic_line_width will store the line skip
1228 i_pic_line_width -= i_pic_width;
1229 p_yuv = p_vout->yuv.yuv.p_rgb8;
1230 p_buffer_start = p_vout->yuv.p_buffer;
1231 p_offset_start = p_vout->yuv.p_offset;
1232 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1233 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1236 * Perform conversion
1238 i_scale_count = i_pic_height;
1239 for( i_y = 0; i_y < i_height; i_y++ )
1241 /* Mark beginnning of line for possible later line copy, and initialize
1243 p_pic_start = p_pic;
1244 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1246 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1247 * pixels wide blocks */
1248 for( i_x = i_width / 16; i_x--; )
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);
1255 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1256 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1257 CONVERT_YUV_PIXEL(1); CONVERT_YUV_PIXEL(1);
1260 /* Do horizontal and vertical scaling */
1262 SCALE_HEIGHT(444, 1);
1266 /*****************************************************************************
1267 * ConvertYUV420RGB16: color YUV 4:2:0 to RGB 2 Bpp
1268 *****************************************************************************/
1269 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,
1270 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1271 int i_matrix_coefficients )
1275 int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
1277 i_chroma_width = i_width / 2;
1278 i_chroma_skip = i_skip / 2;
1279 ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
1280 (i_width + i_skip) * sizeof( yuv_data_t ),
1281 (i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
1282 i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
1283 p_vout->i_screen_depth == 15 );
1285 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1286 int i_vertical_scaling; /* vertical scaling type */
1287 int i_x, i_y; /* horizontal and vertical indexes */
1288 int i_scale_count; /* scale modulo counter */
1289 int i_uval, i_vval; /* U and V samples */
1290 int i_red, i_green, i_blue; /* U and V modified samples */
1291 int i_chroma_width; /* chroma width */
1292 u16 * p_yuv; /* base conversion table */
1293 u16 * p_ybase; /* Y dependant conversion table */
1294 u16 * p_pic_start; /* beginning of the current line for copy */
1295 u16 * p_buffer_start; /* conversion buffer start */
1296 u16 * p_buffer; /* conversion buffer pointer */
1297 int * p_offset_start; /* offset array start */
1298 int * p_offset; /* offset array pointer */
1301 * Initialize some values - i_pic_line_width will store the line skip
1303 i_pic_line_width -= i_pic_width;
1304 i_chroma_width = i_width / 2;
1305 p_yuv = p_vout->yuv.yuv.p_rgb16;
1306 p_buffer_start = p_vout->yuv.p_buffer;
1307 p_offset_start = p_vout->yuv.p_offset;
1308 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1309 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1312 * Perform conversion
1314 i_scale_count = i_pic_height;
1315 for( i_y = 0; i_y < i_height; i_y++ )
1317 /* Mark beginnning of line for possible later line copy, and initialize
1319 p_pic_start = p_pic;
1320 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1322 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1323 * pixels wide blocks */
1324 for( i_x = i_width / 16; i_x--; )
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);
1331 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1332 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1333 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1336 /* Do horizontal and vertical scaling */
1338 SCALE_HEIGHT(420, 2);
1342 /*****************************************************************************
1343 * ConvertYUV422RGB16: color YUV 4:2:2 to RGB 2 Bpp
1344 *****************************************************************************/
1345 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,
1346 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1347 int i_matrix_coefficients )
1349 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1350 int i_vertical_scaling; /* vertical scaling type */
1351 int i_x, i_y; /* horizontal and vertical indexes */
1352 int i_scale_count; /* scale modulo counter */
1353 int i_uval, i_vval; /* U and V samples */
1354 int i_red, i_green, i_blue; /* U and V modified samples */
1355 int i_chroma_width; /* chroma width */
1356 u16 * p_yuv; /* base conversion table */
1357 u16 * p_ybase; /* Y dependant conversion table */
1358 u16 * p_pic_start; /* beginning of the current line for copy */
1359 u16 * p_buffer_start; /* conversion buffer start */
1360 u16 * p_buffer; /* conversion buffer pointer */
1361 int * p_offset_start; /* offset array start */
1362 int * p_offset; /* offset array pointer */
1365 * Initialize some values - i_pic_line_width will store the line skip
1367 i_pic_line_width -= i_pic_width;
1368 i_chroma_width = i_width / 2;
1369 p_yuv = p_vout->yuv.yuv.p_rgb16;
1370 p_buffer_start = p_vout->yuv.p_buffer;
1371 p_offset_start = p_vout->yuv.p_offset;
1372 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1373 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1376 * Perform conversion
1378 i_scale_count = i_pic_height;
1379 for( i_y = 0; i_y < i_height; i_y++ )
1381 /* Mark beginnning of line for possible later line copy, and initialize
1383 p_pic_start = p_pic;
1384 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1386 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1387 * pixels wide blocks */
1388 for( i_x = i_width / 16; i_x--; )
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);
1395 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1396 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1397 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
1400 /* Do horizontal and vertical scaling */
1402 SCALE_HEIGHT(422, 2);
1406 /*****************************************************************************
1407 * ConvertYUV444RGB16: color YUV 4:4:4 to RGB 2 Bpp
1408 *****************************************************************************/
1409 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,
1410 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1411 int i_matrix_coefficients )
1413 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1414 int i_vertical_scaling; /* vertical scaling type */
1415 int i_x, i_y; /* horizontal and vertical indexes */
1416 int i_scale_count; /* scale modulo counter */
1417 int i_uval, i_vval; /* U and V samples */
1418 int i_red, i_green, i_blue; /* U and V modified samples */
1419 int i_chroma_width; /* chroma width, not used */
1420 u16 * p_yuv; /* base conversion table */
1421 u16 * p_ybase; /* Y dependant conversion table */
1422 u16 * p_pic_start; /* beginning of the current line for copy */
1423 u16 * p_buffer_start; /* conversion buffer start */
1424 u16 * p_buffer; /* conversion buffer pointer */
1425 int * p_offset_start; /* offset array start */
1426 int * p_offset; /* offset array pointer */
1429 * Initialize some values - i_pic_line_width will store the line skip
1431 i_pic_line_width -= i_pic_width;
1432 p_yuv = p_vout->yuv.yuv.p_rgb16;
1433 p_buffer_start = p_vout->yuv.p_buffer;
1434 p_offset_start = p_vout->yuv.p_offset;
1435 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1436 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1439 * Perform conversion
1441 i_scale_count = i_pic_height;
1442 for( i_y = 0; i_y < i_height; i_y++ )
1444 /* Mark beginnning of line for possible later line copy, and initialize
1446 p_pic_start = p_pic;
1447 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1449 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1450 * pixels wide blocks */
1451 for( i_x = i_width / 16; i_x--; )
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);
1458 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1459 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1460 CONVERT_YUV_PIXEL(2); CONVERT_YUV_PIXEL(2);
1463 /* Do horizontal and vertical scaling */
1465 SCALE_HEIGHT(444, 2);
1469 /*****************************************************************************
1470 * ConvertYUV420RGB24: color YUV 4:2:0 to RGB 3 Bpp
1471 *****************************************************************************/
1472 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,
1473 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1474 int i_matrix_coefficients )
1479 /*****************************************************************************
1480 * ConvertYUV422RGB24: color YUV 4:2:2 to RGB 3 Bpp
1481 *****************************************************************************/
1482 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,
1483 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1484 int i_matrix_coefficients )
1489 /*****************************************************************************
1490 * ConvertYUV444RGB24: color YUV 4:4:4 to RGB 3 Bpp
1491 *****************************************************************************/
1492 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,
1493 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1494 int i_matrix_coefficients )
1499 /*****************************************************************************
1500 * ConvertYUV420RGB32: color YUV 4:2:0 to RGB 4 Bpp
1501 *****************************************************************************/
1502 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,
1503 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1504 int i_matrix_coefficients )
1506 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1507 int i_vertical_scaling; /* vertical scaling type */
1508 int i_x, i_y; /* horizontal and vertical indexes */
1509 int i_scale_count; /* scale modulo counter */
1510 int i_uval, i_vval; /* U and V samples */
1511 int i_red, i_green, i_blue; /* U and V modified samples */
1512 int i_chroma_width; /* chroma width */
1513 u32 * p_yuv; /* base conversion table */
1514 u32 * p_ybase; /* Y dependant conversion table */
1515 u32 * p_pic_start; /* beginning of the current line for copy */
1516 u32 * p_buffer_start; /* conversion buffer start */
1517 u32 * p_buffer; /* conversion buffer pointer */
1518 int * p_offset_start; /* offset array start */
1519 int * p_offset; /* offset array pointer */
1522 * Initialize some values - i_pic_line_width will store the line skip
1524 i_pic_line_width -= i_pic_width;
1525 i_chroma_width = i_width / 2;
1526 p_yuv = p_vout->yuv.yuv.p_rgb32;
1527 p_buffer_start = p_vout->yuv.p_buffer;
1528 p_offset_start = p_vout->yuv.p_offset;
1529 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1530 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1533 * Perform conversion
1535 i_scale_count = i_pic_height;
1536 for( i_y = 0; i_y < i_height; i_y++ )
1538 /* Mark beginnning of line for possible later line copy, and initialize
1540 p_pic_start = p_pic;
1541 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1543 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1544 * pixels wide blocks */
1545 for( i_x = i_width / 16; i_x--; )
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);
1552 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1553 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1554 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1557 /* Do horizontal and vertical scaling */
1559 SCALE_HEIGHT(420, 4);
1563 /*****************************************************************************
1564 * ConvertYUV422RGB32: color YUV 4:2:2 to RGB 4 Bpp
1565 *****************************************************************************/
1566 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,
1567 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1568 int i_matrix_coefficients )
1570 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1571 int i_vertical_scaling; /* vertical scaling type */
1572 int i_x, i_y; /* horizontal and vertical indexes */
1573 int i_scale_count; /* scale modulo counter */
1574 int i_uval, i_vval; /* U and V samples */
1575 int i_red, i_green, i_blue; /* U and V modified samples */
1576 int i_chroma_width; /* chroma width */
1577 u32 * p_yuv; /* base conversion table */
1578 u32 * p_ybase; /* Y dependant conversion table */
1579 u32 * p_pic_start; /* beginning of the current line for copy */
1580 u32 * p_buffer_start; /* conversion buffer start */
1581 u32 * p_buffer; /* conversion buffer pointer */
1582 int * p_offset_start; /* offset array start */
1583 int * p_offset; /* offset array pointer */
1586 * Initialize some values - i_pic_line_width will store the line skip
1588 i_pic_line_width -= i_pic_width;
1589 i_chroma_width = i_width / 2;
1590 p_yuv = p_vout->yuv.yuv.p_rgb32;
1591 p_buffer_start = p_vout->yuv.p_buffer;
1592 p_offset_start = p_vout->yuv.p_offset;
1593 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1594 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1597 * Perform conversion
1599 i_scale_count = i_pic_height;
1600 for( i_y = 0; i_y < i_height; i_y++ )
1602 /* Mark beginnning of line for possible later line copy, and initialize
1604 p_pic_start = p_pic;
1605 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1607 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1608 * pixels wide blocks */
1609 for( i_x = i_width / 16; i_x--; )
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);
1616 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1617 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1618 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
1621 /* Do horizontal and vertical scaling */
1623 SCALE_HEIGHT(422, 4);
1627 /*****************************************************************************
1628 * ConvertYUV444RGB32: color YUV 4:4:4 to RGB 4 Bpp
1629 *****************************************************************************/
1630 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,
1631 int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
1632 int i_matrix_coefficients )
1634 boolean_t b_horizontal_scaling; /* horizontal scaling type */
1635 int i_vertical_scaling; /* vertical scaling type */
1636 int i_x, i_y; /* horizontal and vertical indexes */
1637 int i_scale_count; /* scale modulo counter */
1638 int i_uval, i_vval; /* U and V samples */
1639 int i_red, i_green, i_blue; /* U and V modified samples */
1640 int i_chroma_width; /* chroma width, not used */
1641 u32 * p_yuv; /* base conversion table */
1642 u32 * p_ybase; /* Y dependant conversion table */
1643 u32 * p_pic_start; /* beginning of the current line for copy */
1644 u32 * p_buffer_start; /* conversion buffer start */
1645 u32 * p_buffer; /* conversion buffer pointer */
1646 int * p_offset_start; /* offset array start */
1647 int * p_offset; /* offset array pointer */
1650 * Initialize some values - i_pic_line_width will store the line skip
1652 i_pic_line_width -= i_pic_width;
1653 p_yuv = p_vout->yuv.yuv.p_rgb32;
1654 p_buffer_start = p_vout->yuv.p_buffer;
1655 p_offset_start = p_vout->yuv.p_offset;
1656 SetOffset( i_width, i_height, i_pic_width, i_pic_height,
1657 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
1660 * Perform conversion
1662 i_scale_count = i_pic_height;
1663 for( i_y = 0; i_y < i_height; i_y++ )
1665 /* Mark beginnning of line for possible later line copy, and initialize
1667 p_pic_start = p_pic;
1668 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
1670 /* Do YUV conversion to buffer - YUV picture is always formed of 16
1671 * pixels wide blocks */
1672 for( i_x = i_width / 16; i_x--; )
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);
1679 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1680 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1681 CONVERT_YUV_PIXEL(4); CONVERT_YUV_PIXEL(4);
1684 /* Do horizontal and vertical scaling */
1686 SCALE_HEIGHT(444, 4);
1690 /*-------------------- walken code follows ----------------------------------*/
1693 * YUV to RGB routines.
1695 * these routines calculate r, g and b values from each pixel's y, u and v.
1696 * these r, g an b values are then passed thru a table lookup to take the
1697 * gamma curve into account and find the corresponding pixel value.
1699 * the table must store more than 3*256 values because of the possibility
1700 * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
1701 * values are in the following intervals :
1702 * -176 to 255+176 for red
1703 * -133 to 255+133 for green
1704 * -222 to 255+222 for blue
1706 * If the input y,u,v values are right, the r,g,b results are not expected
1707 * to move out of the 0 to 255 interval but who knows what will happen in
1710 * the red, green and blue conversion tables are stored in a single 1935-entry
1711 * array. The respective positions of each component in the array have been
1712 * calculated to minimize the cache interactions of the 3 tables.
1717 static void yuvToRgb24 (unsigned char * Y,
1718 unsigned char * U, unsigned char * V,
1719 char * dest, int table[1935], int width)
1734 uvRed = (V_RED_COEF*v) >> SHIFT;
1735 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1736 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1738 tableY = table + *(Y++);
1739 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1740 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1742 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1744 *(dest++) = tmp24 >> 8;
1745 *(dest++) = tmp24 >> 16;
1747 tableY = table + *(Y++);
1748 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1749 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1751 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1753 *(dest++) = tmp24 >> 8;
1754 *(dest++) = tmp24 >> 16;
1758 uvRed = (V_RED_COEF*v) >> SHIFT;
1759 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1760 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1762 tableY = table + *(Y++);
1763 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1764 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1766 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1768 *(dest++) = tmp24 >> 8;
1769 *(dest++) = tmp24 >> 16;
1771 tableY = table + *(Y++);
1772 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1773 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1775 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1777 *(dest++) = tmp24 >> 8;
1778 *(dest++) = tmp24 >> 16;
1782 uvRed = (V_RED_COEF*v) >> SHIFT;
1783 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1784 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1786 tableY = table + *(Y++);
1787 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1788 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1790 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1792 *(dest++) = tmp24 >> 8;
1793 *(dest++) = tmp24 >> 16;
1795 tableY = table + *(Y++);
1796 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1797 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1799 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1801 *(dest++) = tmp24 >> 8;
1802 *(dest++) = tmp24 >> 16;
1806 uvRed = (V_RED_COEF*v) >> SHIFT;
1807 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1808 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
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;
1819 tableY = table + *(Y++);
1820 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1821 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1823 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1825 *(dest++) = tmp24 >> 8;
1826 *(dest++) = tmp24 >> 16;
1829 i = (width & 7) >> 1;
1833 uvRed = (V_RED_COEF*v) >> SHIFT;
1834 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1835 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1837 tableY = table + *(Y++);
1838 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1839 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1841 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1843 *(dest++) = tmp24 >> 8;
1844 *(dest++) = tmp24 >> 16;
1846 tableY = table + *(Y++);
1847 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1848 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1850 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1852 *(dest++) = tmp24 >> 8;
1853 *(dest++) = tmp24 >> 16;
1859 uvRed = (V_RED_COEF*v) >> SHIFT;
1860 uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
1861 uvBlue = (U_BLUE_COEF*u) >> SHIFT;
1863 tableY = table + *(Y++);
1864 tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
1865 tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
1867 tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
1869 *(dest++) = tmp24 >> 8;
1870 *(dest++) = tmp24 >> 16;