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.1 2002/08/04 17:23:43 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_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 int Activate ( vlc_object_t * );
49 static void I420_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
50 static void I420_YVYU ( vout_thread_t *, picture_t *, picture_t * );
51 static void I420_UYVY ( vout_thread_t *, picture_t *, picture_t * );
52 static void I420_IUYV ( vout_thread_t *, picture_t *, picture_t * );
53 static void I420_cyuv ( vout_thread_t *, picture_t *, picture_t * );
54 #if defined (MODULE_NAME_IS_i420_yuy2)
55 static void I420_Y211 ( vout_thread_t *, picture_t *, picture_t * );
58 #ifdef MODULE_NAME_IS_i420_yuy2_mmx
59 static unsigned long long i_00ffw;
60 static unsigned long long i_80w;
63 /*****************************************************************************
65 *****************************************************************************/
67 #if defined (MODULE_NAME_IS_i420_yuy2)
68 set_description( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) );
69 set_capability( "chroma", 80 );
70 #elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
71 set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
72 set_capability( "chroma", 100 );
73 add_requirement( MMX );
74 /* Initialize MMX-specific constants */
75 i_00ffw = 0x00ff00ff00ff00ff;
76 i_80w = 0x0000000080808080;
78 set_callbacks( Activate, NULL );
81 /*****************************************************************************
82 * Activate: allocate a chroma function
83 *****************************************************************************
84 * This function allocates and initializes a chroma function
85 *****************************************************************************/
86 static int Activate( vlc_object_t *p_this )
88 vout_thread_t *p_vout = (vout_thread_t *)p_this;
90 if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
95 switch( p_vout->render.i_chroma )
97 case VLC_FOURCC('Y','V','1','2'):
98 case VLC_FOURCC('I','4','2','0'):
99 case VLC_FOURCC('I','Y','U','V'):
100 switch( p_vout->output.i_chroma )
102 case VLC_FOURCC('Y','U','Y','2'):
103 case VLC_FOURCC('Y','U','N','V'):
104 p_vout->chroma.pf_convert = I420_YUY2;
107 case VLC_FOURCC('Y','V','Y','U'):
108 p_vout->chroma.pf_convert = I420_YVYU;
111 case VLC_FOURCC('U','Y','V','Y'):
112 case VLC_FOURCC('U','Y','N','V'):
113 case VLC_FOURCC('Y','4','2','2'):
114 p_vout->chroma.pf_convert = I420_UYVY;
117 case VLC_FOURCC('I','U','Y','V'):
118 p_vout->chroma.pf_convert = I420_IUYV;
121 case VLC_FOURCC('c','y','u','v'):
122 p_vout->chroma.pf_convert = I420_cyuv;
125 #if defined (MODULE_NAME_IS_i420_yuy2)
126 case VLC_FOURCC('Y','2','1','1'):
127 p_vout->chroma.pf_convert = I420_Y211;
143 /* Following functions are local */
145 /*****************************************************************************
146 * I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
147 *****************************************************************************/
148 static void I420_YUY2( vout_thread_t *p_vout, picture_t *p_source,
151 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
152 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
153 u8 *p_u = p_source->U_PIXELS;
154 u8 *p_v = p_source->V_PIXELS;
158 const int i_source_margin = p_source->p->i_pitch
159 - p_source->p->i_visible_pitch;
160 const int i_dest_margin = p_dest->p->i_pitch
161 - p_dest->p->i_visible_pitch;
163 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
166 p_line2 += p_dest->p->i_pitch;
169 p_y2 += p_source->p[Y_PLANE].i_pitch;
171 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
173 #if defined (MODULE_NAME_IS_i420_yuy2)
179 MMX_CALL( MMX_YUV420_YUYV );
183 p_y1 += i_source_margin;
184 p_y2 += i_source_margin;
185 p_line1 += i_dest_margin;
186 p_line2 += i_dest_margin;
190 /*****************************************************************************
191 * I420_YVYU: planar YUV 4:2:0 to packed YVYU 4:2:2
192 *****************************************************************************/
193 static void I420_YVYU( vout_thread_t *p_vout, picture_t *p_source,
196 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
197 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
198 u8 *p_u = p_source->U_PIXELS;
199 u8 *p_v = p_source->V_PIXELS;
203 const int i_source_margin = p_source->p->i_pitch
204 - p_source->p->i_visible_pitch;
205 const int i_dest_margin = p_dest->p->i_pitch
206 - p_dest->p->i_visible_pitch;
208 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
211 p_line2 += p_dest->p->i_pitch;
214 p_y2 += p_source->p[Y_PLANE].i_pitch;
216 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
218 #if defined (MODULE_NAME_IS_i420_yuy2)
224 MMX_CALL( MMX_YUV420_YVYU );
228 p_y1 += i_source_margin;
229 p_y2 += i_source_margin;
230 p_line1 += i_dest_margin;
231 p_line2 += i_dest_margin;
235 /*****************************************************************************
236 * I420_UYVY: planar YUV 4:2:0 to packed UYVY 4:2:2
237 *****************************************************************************/
238 static void I420_UYVY( vout_thread_t *p_vout, picture_t *p_source,
241 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
242 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
243 u8 *p_u = p_source->U_PIXELS;
244 u8 *p_v = p_source->V_PIXELS;
248 const int i_source_margin = p_source->p->i_pitch
249 - p_source->p->i_visible_pitch;
250 const int i_dest_margin = p_dest->p->i_pitch
251 - p_dest->p->i_visible_pitch;
253 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
256 p_line2 += p_dest->p->i_pitch;
259 p_y2 += p_source->p[Y_PLANE].i_pitch;
261 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
263 #if defined (MODULE_NAME_IS_i420_yuy2)
269 MMX_CALL( MMX_YUV420_UYVY );
273 p_y1 += i_source_margin;
274 p_y2 += i_source_margin;
275 p_line1 += i_dest_margin;
276 p_line2 += i_dest_margin;
280 /*****************************************************************************
281 * I420_IUYV: planar YUV 4:2:0 to interleaved packed UYVY 4:2:2
282 *****************************************************************************/
283 static void I420_IUYV( vout_thread_t *p_vout, picture_t *p_source,
287 msg_Err( p_vout, "I420_IUYV unimplemented, please harass <sam@zoy.org>" );
290 /*****************************************************************************
291 * I420_cyuv: planar YUV 4:2:0 to upside-down packed UYVY 4:2:2
292 *****************************************************************************/
293 static void I420_cyuv( vout_thread_t *p_vout, picture_t *p_source,
296 u8 *p_line1 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch
297 + p_dest->p->i_pitch;
298 u8 *p_line2 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
299 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
300 u8 *p_u = p_source->U_PIXELS;
301 u8 *p_v = p_source->V_PIXELS;
305 const int i_source_margin = p_source->p->i_pitch
306 - p_source->p->i_visible_pitch;
307 const int i_dest_margin = p_dest->p->i_pitch
308 - p_dest->p->i_visible_pitch;
310 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
312 p_line1 -= 3 * p_dest->p->i_pitch;
313 p_line2 -= 3 * p_dest->p->i_pitch;
316 p_y2 += p_source->p[Y_PLANE].i_pitch;
318 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
320 #if defined (MODULE_NAME_IS_i420_yuy2)
326 MMX_CALL( MMX_YUV420_UYVY );
330 p_y1 += i_source_margin;
331 p_y2 += i_source_margin;
332 p_line1 += i_dest_margin;
333 p_line2 += i_dest_margin;
337 /*****************************************************************************
338 * I420_Y211: planar YUV 4:2:0 to packed YUYV 2:1:1
339 *****************************************************************************/
340 #if defined (MODULE_NAME_IS_i420_yuy2)
341 static void I420_Y211( vout_thread_t *p_vout, picture_t *p_source,
344 u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
345 u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
346 u8 *p_u = p_source->U_PIXELS;
347 u8 *p_v = p_source->V_PIXELS;
351 const int i_source_margin = p_source->p->i_pitch
352 - p_source->p->i_visible_pitch;
353 const int i_dest_margin = p_dest->p->i_pitch
354 - p_dest->p->i_visible_pitch;
356 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
359 p_line2 += p_dest->p->i_pitch;
362 p_y2 += p_source->p[Y_PLANE].i_pitch;
364 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
370 p_y1 += i_source_margin;
371 p_y2 += i_source_margin;
372 p_line1 += i_dest_margin;
373 p_line2 += i_dest_margin;