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.1 2001/12/16 16:18:36 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 #define MODULE_NAME yv12_rgb8.c
25 #include "modules_inner.h"
27 /*****************************************************************************
29 *****************************************************************************/
32 #include <math.h> /* exp(), pow() */
33 #include <errno.h> /* ENOMEM */
34 #include <string.h> /* strerror() */
35 #include <stdlib.h> /* malloc(), free() */
38 #include "common.h" /* boolean_t, byte_t */
43 #include "video_output.h"
45 #include "chroma_common.h"
46 #include "transforms.h"
49 #include "modules_export.h"
51 /*****************************************************************************
52 * chroma_sys_t: chroma method descriptor
53 *****************************************************************************
54 * This structure is part of the chroma transformation descriptor, it
55 * describes the yuv2rgb8 specific properties.
56 *****************************************************************************/
57 typedef struct chroma_sys_s
64 /*****************************************************************************
65 * Local and extern prototypes.
66 *****************************************************************************/
67 static void chroma_getfunctions ( function_list_t * p_function_list );
69 static int chroma_Probe ( probedata_t *p_data );
70 static int chroma_Init ( vout_thread_t *p_vout, probedata_t *p_data );
71 static int chroma_End ( vout_thread_t *p_vout );
73 static void ConvertY4Gray8 ( vout_thread_t *, picture_t *, picture_t * );
74 static void ConvertYUV420RGB8 ( vout_thread_t *, picture_t *, picture_t * );
76 /*****************************************************************************
77 * Build configuration tree.
78 *****************************************************************************/
80 ADD_WINDOW( "Configuration for YV12 to RGB8 module" )
81 ADD_COMMENT( "Ha, ha -- nothing to configure yet" )
85 p_module->i_capabilities = MODULE_CAPABILITY_NULL
86 | MODULE_CAPABILITY_CHROMA;
87 p_module->psz_longname = "YV12 to paletted RGB8 conversion module";
91 _M( chroma_getfunctions )( &p_module->p_functions->chroma );
94 MODULE_DEACTIVATE_START
95 MODULE_DEACTIVATE_STOP
97 /*****************************************************************************
99 *****************************************************************************/
100 /*****************************************************************************
101 * Functions exported as capabilities. They are declared as static so that
102 * we don't pollute the namespace too much.
103 *****************************************************************************/
104 void _M( chroma_getfunctions )( function_list_t * p_function_list )
106 p_function_list->pf_probe = chroma_Probe;
107 p_function_list->functions.chroma.pf_init = chroma_Init;
108 p_function_list->functions.chroma.pf_end = chroma_End;
111 /*****************************************************************************
112 * chroma_Probe: return a score
113 *****************************************************************************
114 * This function checks that we can handle the required data
115 *****************************************************************************/
116 static int chroma_Probe( probedata_t *p_data )
118 if( p_data->chroma.source.i_chroma != YUV_420_PICTURE
119 || p_data->chroma.dest.i_chroma != RGB_8BPP_PICTURE )
127 /*****************************************************************************
128 * chroma_Init: allocate a chroma function
129 *****************************************************************************
130 * This function allocates and initializes a chroma function
131 *****************************************************************************/
132 static int chroma_Init( vout_thread_t *p_vout, probedata_t *p_data )
134 if( p_data->chroma.source.i_chroma != YUV_420_PICTURE
135 || p_data->chroma.dest.i_chroma != RGB_8BPP_PICTURE )
140 p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) );
141 if( p_vout->chroma.p_sys == NULL )
146 p_vout->chroma.p_sys->p_tables = malloc( sizeof( u8 ) *
147 (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE) );
148 if( p_vout->chroma.p_sys->p_tables == NULL )
150 free( p_vout->chroma.p_sys );
154 p_vout->chroma.p_sys->p_buffer = malloc( sizeof( u8 ) * VOUT_MAX_WIDTH );
155 if( p_vout->chroma.p_sys->p_buffer == NULL )
157 free( p_vout->chroma.p_sys->p_tables );
158 free( p_vout->chroma.p_sys );
162 p_vout->chroma.p_sys->p_offset = malloc( sizeof( int ) *
163 2 * p_data->chroma.dest.i_width );
164 if( p_vout->chroma.p_sys->p_buffer == NULL )
166 free( p_vout->chroma.p_sys->p_offset );
167 free( p_vout->chroma.p_sys->p_tables );
168 free( p_vout->chroma.p_sys );
177 /*****************************************************************************
178 * chroma_End: free the chroma function
179 *****************************************************************************
180 * This function frees the previously allocated chroma function
181 *****************************************************************************/
182 static int chroma_End( vout_thread_t *p_vout )
187 /* Following functions are local */
190 /*****************************************************************************
191 * ConvertY4Gray8: grayscale YUV 4:x:x to RGB 8 bpp
192 *****************************************************************************/
193 static void ConvertY4Gray8( vout_thread_t *p_vout, picture_t *p_source,
196 boolean_t b_horizontal_scaling; /* horizontal scaling type */
197 int i_vertical_scaling; /* vertical scaling type */
198 int i_x, i_y; /* horizontal and vertical indexes */
199 int i_scale_count; /* scale modulo counter */
200 int i_chroma_width; /* chroma width, not used */
201 u8 * p_gray; /* base conversion table */
202 u8 * p_pic_start; /* beginning of the current line for copy */
203 u8 * p_buffer_start; /* conversion buffer start */
204 u8 * p_buffer; /* conversion buffer pointer */
205 int * p_offset_start; /* offset array start */
206 int * p_offset; /* offset array pointer */
209 * Initialize some values - i_pic_line_width will store the line skip
211 // i_pic_line_width -= i_pic_width;
212 p_gray = p_vout->chroma.p_sys->p_gray8;
213 p_buffer_start = p_vout->chroma.p_sys->p_buffer;
214 p_offset_start = p_vout->chroma.p_sys->p_offset;
215 _M( SetOffset )( i_width, i_height, i_pic_width, i_pic_height,
216 &b_horizontal_scaling, &i_vertical_scaling, p_offset_start, 0 );
221 i_scale_count = ( i_vertical_scaling == 1 ) ? i_pic_height : i_height;
222 for( i_y = 0; i_y < i_height; i_y++ )
224 /* Mark beginnning of line for possible later line copy, and initialize
227 p_buffer = b_horizontal_scaling ? p_buffer_start : p_pic;
229 /* Do YUV conversion to buffer - YUV picture is always formed of 16
230 * pixels wide blocks */
231 for( i_x = i_width / 16; i_x--; )
233 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
234 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
235 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
236 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
237 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
238 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
239 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
240 *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
243 /* Do horizontal and vertical scaling */
245 SCALE_HEIGHT(400, 1);
250 /*****************************************************************************
251 * ConvertYUV420RGB8: color YUV 4:2:0 to RGB 8 bpp
252 *****************************************************************************/
253 static void ConvertYUV420RGB8( vout_thread_t *p_vout, picture_t *p_source,
256 printf( "Colorspace transformation, YV12 to RGB8\n");
258 boolean_t b_horizontal_scaling; /* horizontal scaling type */
259 int i_vertical_scaling; /* vertical scaling type */
260 int i_x, i_y; /* horizontal and vertical indexes */
261 int i_scale_count; /* scale modulo counter */
262 int i_real_y; /* y % 4 */
263 u8 * p_lookup; /* lookup table */
264 int i_chroma_width; /* chroma width */
265 u8 * p_offset_start; /* offset array start */
266 u8 * p_offset; /* offset array pointer */
268 int i_pic_line_width = p_source->i_width; /* XXX not sure */
269 int i_width = p_source->i_width;
270 int i_height = p_source->i_height;
271 int i_pic_width = p_dest->i_width;
272 int i_pic_height = p_dest->i_height;
273 u8* p_y = p_source->planes[ Y_PLANE ].p_data;
274 u8* p_u = p_source->planes[ U_PLANE ].p_data;
275 u8* p_v = p_source->planes[ V_PLANE ].p_data;
276 u8* p_pic = p_dest->planes[ RGB_PLANE ].p_data;
279 * The dithering matrices
281 static int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
282 static int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
283 static int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
284 static int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
286 static int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
287 static int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
288 static int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
289 static int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
292 * Initialize some values - i_pic_line_width will store the line skip
294 i_pic_line_width -= p_dest->i_width; /*i_pic_width*/
295 i_chroma_width = p_source->i_width / 2;
296 p_offset_start = p_vout->chroma.p_sys->p_offset;
297 p_lookup = p_vout->chroma.p_sys->p_tables;
298 _M( SetOffset )( p_source->i_width, p_source->i_height,
299 p_dest->i_width, p_dest->i_height,
300 &b_horizontal_scaling, &i_vertical_scaling,
306 i_scale_count = ( i_vertical_scaling == 1 ) ? p_dest->i_height : p_source->i_height;
308 for( i_y = 0; i_y < p_source->i_height; i_y++ )
310 /* Do horizontal and vertical scaling */
311 SCALE_WIDTH_DITHER( 420 );
312 SCALE_HEIGHT_DITHER( 420 );