1 /*****************************************************************************
2 * yv12_rgb8.c : YUV to paletted RGB8 conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000 VideoLAN
5 * $Id: yv12_rgb8.c,v 1.4 2002/01/02 14:37:42 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <math.h> /* exp(), pow() */
28 #include <errno.h> /* ENOMEM */
29 #include <string.h> /* strerror() */
30 #include <stdlib.h> /* malloc(), free() */
32 #include <videolan/vlc.h>
35 #include "video_output.h"
37 #include "chroma_common.h"
38 #include "transforms.h"
40 /*****************************************************************************
41 * chroma_sys_t: chroma method descriptor
42 *****************************************************************************
43 * This structure is part of the chroma transformation descriptor, it
44 * describes the yuv2rgb8 specific properties.
45 *****************************************************************************/
46 typedef struct chroma_sys_s
53 /*****************************************************************************
54 * Local and extern prototypes.
55 *****************************************************************************/
56 static void chroma_getfunctions ( function_list_t * p_function_list );
58 static int chroma_Probe ( probedata_t *p_data );
59 static int chroma_Init ( vout_thread_t *p_vout, probedata_t *p_data );
60 static int chroma_End ( vout_thread_t *p_vout );
62 static void ConvertY4Gray8 ( vout_thread_t *, picture_t *, picture_t * );
63 static void ConvertYUV420RGB8 ( vout_thread_t *, picture_t *, picture_t * );
65 /*****************************************************************************
66 * Build configuration tree.
67 *****************************************************************************/
72 SET_DESCRIPTION( "YV12 to RGB8 conversion module" )
73 ADD_CAPABILITY( CHROMA, 50 )
77 _M( chroma_getfunctions )( &p_module->p_functions->chroma );
80 MODULE_DEACTIVATE_START
81 MODULE_DEACTIVATE_STOP
83 /*****************************************************************************
85 *****************************************************************************/
86 /*****************************************************************************
87 * Functions exported as capabilities. They are declared as static so that
88 * we don't pollute the namespace too much.
89 *****************************************************************************/
90 void _M( chroma_getfunctions )( function_list_t * p_function_list )
92 p_function_list->pf_probe = chroma_Probe;
93 p_function_list->functions.chroma.pf_init = chroma_Init;
94 p_function_list->functions.chroma.pf_end = chroma_End;
97 /*****************************************************************************
98 * chroma_Probe: return a score
99 *****************************************************************************
100 * This function checks that we can handle the required data
101 *****************************************************************************/
102 static int chroma_Probe( probedata_t *p_data )
104 if( p_data->chroma.source.i_chroma != YUV_420_PICTURE
105 || p_data->chroma.dest.i_chroma != RGB_8BPP_PICTURE )
113 /*****************************************************************************
114 * chroma_Init: allocate a chroma function
115 *****************************************************************************
116 * This function allocates and initializes a chroma function
117 *****************************************************************************/
118 static int chroma_Init( vout_thread_t *p_vout, probedata_t *p_data )
120 if( p_data->chroma.source.i_chroma != YUV_420_PICTURE
121 || p_data->chroma.dest.i_chroma != RGB_8BPP_PICTURE )
126 p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) );
127 if( p_vout->chroma.p_sys == NULL )
132 p_vout->chroma.p_sys->p_tables = malloc( sizeof( u8 ) *
133 (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE) );
134 if( p_vout->chroma.p_sys->p_tables == NULL )
136 free( p_vout->chroma.p_sys );
140 p_vout->chroma.p_sys->p_buffer = malloc( sizeof( u8 ) * VOUT_MAX_WIDTH );
141 if( p_vout->chroma.p_sys->p_buffer == NULL )
143 free( p_vout->chroma.p_sys->p_tables );
144 free( p_vout->chroma.p_sys );
148 p_vout->chroma.p_sys->p_offset = malloc( sizeof( int ) *
149 2 * p_data->chroma.dest.i_width );
150 if( p_vout->chroma.p_sys->p_buffer == NULL )
152 free( p_vout->chroma.p_sys->p_offset );
153 free( p_vout->chroma.p_sys->p_tables );
154 free( p_vout->chroma.p_sys );
163 /*****************************************************************************
164 * chroma_End: free the chroma function
165 *****************************************************************************
166 * This function frees the previously allocated chroma function
167 *****************************************************************************/
168 static int chroma_End( vout_thread_t *p_vout )
173 /* Following functions are local */
176 /*****************************************************************************
177 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
178 *****************************************************************************/
179 static void ConvertY4Gray8( vout_thread_t *p_vout, picture_t *p_source,
182 boolean_t b_horizontal_scaling; /* horizontal scaling type */
183 int i_vertical_scaling; /* vertical scaling type */
184 int i_x, i_y; /* horizontal and vertical indexes */
185 int i_scale_count; /* scale modulo counter */
186 int i_chroma_width; /* chroma width, not used */
187 u8 * p_gray; /* base conversion table */
188 u8 * p_pic_start; /* beginning of the current line for copy */
189 u8 * p_buffer_start; /* conversion buffer start */
190 u8 * p_buffer; /* conversion buffer pointer */
191 int * p_offset_start; /* offset array start */
192 int * p_offset; /* offset array pointer */
195 * Initialize some values - i_pic_line_width will store the line skip
197 // i_pic_line_width -= i_pic_width;
198 p_gray = p_vout->chroma.p_sys->p_gray8;
199 p_buffer_start = p_vout->chroma.p_sys->p_buffer;
200 p_offset_start = p_vout->chroma.p_sys->p_offset;
201 _M( SetOffset )( i_width, i_height, i_pic_width, i_pic_height,
202 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
207 i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
208 for( i_y = 0; i_y < i_height; i_y++ )
210 /* Mark beginnning of line for possible later line copy, and initialize
213 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
215 /* Do YUV conversion to buffer - YUV picture is always formed of 16
216 * pixels wide blocks */
217 for( i_x = i_width / 16; i_x--; )
219 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
220 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
221 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
222 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
223 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
224 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
225 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
226 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
229 /* Do horizontal and vertical scaling */
231 SCALE_HEIGHT(400, 1);
236 /*****************************************************************************
237 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
238 *****************************************************************************/
239 static void ConvertYUV420RGB8( vout_thread_t *p_vout, picture_t *p_source,
242 printf( "Colorspace transformation, YV12 to RGB8\n");
244 boolean_t b_horizontal_scaling; /* horizontal scaling type */
245 int i_vertical_scaling; /* vertical scaling type */
246 int i_x, i_y; /* horizontal and vertical indexes */
247 int i_scale_count; /* scale modulo counter */
248 int i_real_y; /* y % 4 */
249 u8 * p_lookup; /* lookup table */
250 int i_chroma_width; /* chroma width */
251 u8 * p_offset_start; /* offset array start */
252 u8 * p_offset; /* offset array pointer */
254 int i_pic_line_width = p_source->i_width; /* XXX not sure */
255 int i_width = p_source->i_width;
256 int i_height = p_source->i_height;
257 int i_pic_width = p_dest->i_width;
258 int i_pic_height = p_dest->i_height;
259 u8* p_y = p_source->planes[ Y_PLANE ].p_data;
260 u8* p_u = p_source->planes[ U_PLANE ].p_data;
261 u8* p_v = p_source->planes[ V_PLANE ].p_data;
262 u8* p_pic = p_dest->planes[ MAIN_PLANE ].p_data;
265 * The dithering matrices
267 static int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
268 static int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
269 static int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
270 static int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
272 static int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
273 static int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
274 static int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
275 static int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
278 * Initialize some values - i_pic_line_width will store the line skip
280 i_pic_line_width -= p_dest->i_width; /*i_pic_width*/
281 i_chroma_width = p_source->i_width / 2;
282 p_offset_start = p_vout->chroma.p_sys->p_offset;
283 p_lookup = p_vout->chroma.p_sys->p_tables;
284 _M( SetOffset )( p_source->i_width, p_source->i_height,
285 p_dest->i_width, p_dest->i_height,
286 &b_horizontal_scaling, &i_vertical_scaling,
292 i_scale_count = ( i_vertical_scaling == 1 ) ? p_dest->i_height : p_source->i_height;
294 for( i_y = 0; i_y < p_source->i_height; i_y++ )
296 /* Do horizontal and vertical scaling */
297 SCALE_WIDTH_DITHER( 420 );
298 SCALE_HEIGHT_DITHER( 420 );