1 /*****************************************************************************
2 * i420_yuy2.c : YUV to YUV conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: i420_yuy2.c,v 1.8 2002/06/01 12:31:58 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 <errno.h> /* ENOMEM */
28 #include <string.h> /* strerror() */
29 #include <stdlib.h> /* malloc(), free() */
34 #include "i420_yuy2.h"
36 #define SRC_FOURCC "I420,IYUV,YV12"
38 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
39 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
41 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
44 /*****************************************************************************
45 * Local and extern prototypes.
46 *****************************************************************************/
47 static void chroma_getfunctions ( function_list_t * p_function_list );
49 static int chroma_Init ( vout_thread_t *p_vout );
50 static void chroma_End ( vout_thread_t *p_vout );
52 static void I420_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
53 static void I420_YVYU ( vout_thread_t *, picture_t *, picture_t * );
54 static void I420_UYVY ( vout_thread_t *, picture_t *, picture_t * );
55 static void I420_IUYV ( vout_thread_t *, picture_t *, picture_t * );
56 static void I420_cyuv ( vout_thread_t *, picture_t *, picture_t * );
57 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
58 static void I420_Y211 ( vout_thread_t *, picture_t *, picture_t * );
61 /*****************************************************************************
62 * Build configuration tree.
63 *****************************************************************************/
68 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
69 SET_DESCRIPTION( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) )
70 ADD_CAPABILITY( CHROMA, 80 )
71 #elif defined (MODULE_NAME_IS_chroma_i420_yuy2_mmx)
72 SET_DESCRIPTION( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) )
73 ADD_CAPABILITY( CHROMA, 100 )
74 ADD_REQUIREMENT( MMX )
79 chroma_getfunctions( &p_module->p_functions->chroma );
82 MODULE_DEACTIVATE_START
83 MODULE_DEACTIVATE_STOP
85 /*****************************************************************************
86 * Functions exported as capabilities. They are declared as static so that
87 * we don't pollute the namespace too much.
88 *****************************************************************************/
89 static void chroma_getfunctions( function_list_t * p_function_list )
91 p_function_list->functions.chroma.pf_init = chroma_Init;
92 p_function_list->functions.chroma.pf_end = chroma_End;
95 /*****************************************************************************
96 * chroma_Init: allocate a chroma function
97 *****************************************************************************
98 * This function allocates and initializes a chroma function
99 *****************************************************************************/
100 static int chroma_Init( vout_thread_t *p_vout )
102 if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
107 switch( p_vout->render.i_chroma )
112 switch( p_vout->output.i_chroma )
116 p_vout->chroma.pf_convert = I420_YUY2;
120 p_vout->chroma.pf_convert = I420_YVYU;
126 p_vout->chroma.pf_convert = I420_UYVY;
130 p_vout->chroma.pf_convert = I420_IUYV;
134 p_vout->chroma.pf_convert = I420_cyuv;
137 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
139 p_vout->chroma.pf_convert = I420_Y211;
155 /*****************************************************************************
156 * chroma_End: free the chroma function
157 *****************************************************************************
158 * This function frees the previously allocated chroma function
159 *****************************************************************************/
160 static void chroma_End( vout_thread_t *p_vout )
165 /* Following functions are local */
167 /*****************************************************************************
168 * I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
169 *****************************************************************************/
170 static void I420_YUY2( vout_thread_t *p_vout, picture_t *p_source,
173 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
174 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
175 u8 *p_u = p_source->U_PIXELS;
176 u8 *p_v = p_source->V_PIXELS;
180 const int i_source_margin = p_source->p->b_margin ?
181 p_source->p->i_pitch - p_source->p->i_visible_bytes : 0;
182 const int i_dest_margin = p_dest->p->b_margin ?
183 p_dest->p->i_pitch - p_dest->p->i_visible_bytes : 0;
185 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
188 p_line2 += p_dest->p->i_pitch;
191 p_y2 += p_source->p[Y_PLANE].i_pitch;
193 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
195 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
201 MMX_CALL( MMX_YUV420_YUYV );
205 p_y1 += i_source_margin;
206 p_y2 += i_source_margin;
207 p_line1 += i_dest_margin;
208 p_line2 += i_dest_margin;
212 /*****************************************************************************
213 * I420_YVYU: planar YUV 4:2:0 to packed YVYU 4:2:2
214 *****************************************************************************/
215 static void I420_YVYU( vout_thread_t *p_vout, picture_t *p_source,
218 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
219 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
220 u8 *p_u = p_source->U_PIXELS;
221 u8 *p_v = p_source->V_PIXELS;
225 const int i_source_margin = p_source->p->b_margin ?
226 p_source->p->i_pitch - p_source->p->i_visible_bytes : 0;
227 const int i_dest_margin = p_dest->p->b_margin ?
228 p_dest->p->i_pitch - p_dest->p->i_visible_bytes : 0;
230 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
233 p_line2 += p_dest->p->i_pitch;
236 p_y2 += p_source->p[Y_PLANE].i_pitch;
238 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
240 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
246 MMX_CALL( MMX_YUV420_YVYU );
250 p_y1 += i_source_margin;
251 p_y2 += i_source_margin;
252 p_line1 += i_dest_margin;
253 p_line2 += i_dest_margin;
257 /*****************************************************************************
258 * I420_UYVY: planar YUV 4:2:0 to packed UYVY 4:2:2
259 *****************************************************************************/
260 static void I420_UYVY( vout_thread_t *p_vout, picture_t *p_source,
263 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
264 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
265 u8 *p_u = p_source->U_PIXELS;
266 u8 *p_v = p_source->V_PIXELS;
270 const int i_source_margin = p_source->p->b_margin ?
271 p_source->p->i_pitch - p_source->p->i_visible_bytes : 0;
272 const int i_dest_margin = p_dest->p->b_margin ?
273 p_dest->p->i_pitch - p_dest->p->i_visible_bytes : 0;
275 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
278 p_line2 += p_dest->p->i_pitch;
281 p_y2 += p_source->p[Y_PLANE].i_pitch;
283 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
285 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
291 MMX_CALL( MMX_YUV420_UYVY );
295 p_y1 += i_source_margin;
296 p_y2 += i_source_margin;
297 p_line1 += i_dest_margin;
298 p_line2 += i_dest_margin;
302 /*****************************************************************************
303 * I420_IUYV: planar YUV 4:2:0 to interleaved packed UYVY 4:2:2
304 *****************************************************************************/
305 static void I420_IUYV( vout_thread_t *p_vout, picture_t *p_source,
309 msg_Err( p_vout, "I420_IUYV unimplemented, please harass <sam@zoy.org>" );
312 /*****************************************************************************
313 * I420_cyuv: planar YUV 4:2:0 to upside-down packed UYVY 4:2:2
314 *****************************************************************************/
315 static void I420_cyuv( vout_thread_t *p_vout, picture_t *p_source,
318 u8 *p_line1 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch
319 + p_dest->p->i_pitch;
320 u8 *p_line2 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
321 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
322 u8 *p_u = p_source->U_PIXELS;
323 u8 *p_v = p_source->V_PIXELS;
327 const int i_source_margin = p_source->p->b_margin ?
328 p_source->p->i_pitch - p_source->p->i_visible_bytes : 0;
329 const int i_dest_margin = p_dest->p->b_margin ?
330 p_dest->p->i_pitch - p_dest->p->i_visible_bytes : 0;
332 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
334 p_line1 -= 3 * p_dest->p->i_pitch;
335 p_line2 -= 3 * p_dest->p->i_pitch;
338 p_y2 += p_source->p[Y_PLANE].i_pitch;
340 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
342 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
348 MMX_CALL( MMX_YUV420_UYVY );
352 p_y1 += i_source_margin;
353 p_y2 += i_source_margin;
354 p_line1 += i_dest_margin;
355 p_line2 += i_dest_margin;
359 /*****************************************************************************
360 * I420_Y211: planar YUV 4:2:0 to packed YUYV 2:1:1
361 *****************************************************************************/
362 #if defined (MODULE_NAME_IS_chroma_i420_yuy2)
363 static void I420_Y211( vout_thread_t *p_vout, picture_t *p_source,
366 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
367 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
368 u8 *p_u = p_source->U_PIXELS;
369 u8 *p_v = p_source->V_PIXELS;
373 const int i_source_margin = p_source->p->b_margin ?
374 p_source->p->i_pitch - p_source->p->i_visible_bytes : 0;
375 const int i_dest_margin = p_dest->p->b_margin ?
376 p_dest->p->i_pitch - p_dest->p->i_visible_bytes : 0;
378 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
381 p_line2 += p_dest->p->i_pitch;
384 p_y2 += p_source->p[Y_PLANE].i_pitch;
386 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
392 p_y1 += i_source_margin;
393 p_y2 += i_source_margin;
394 p_line1 += i_dest_margin;
395 p_line2 += i_dest_margin;