1 /*****************************************************************************
2 * i422_yuy2.c : Planar YUV 4:2:2 to Packed YUV conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 the VideoLAN team
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Damien Fouilleul <damienf@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include "i422_yuy2.h"
34 #define SRC_FOURCC "I422"
35 #if defined (MODULE_NAME_IS_i422_yuy2)
36 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
38 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
41 /*****************************************************************************
42 * Local and extern prototypes.
43 *****************************************************************************/
44 static int Activate ( vlc_object_t * );
46 static void I422_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
47 static void I422_YVYU ( vout_thread_t *, picture_t *, picture_t * );
48 static void I422_UYVY ( vout_thread_t *, picture_t *, picture_t * );
49 static void I422_IUYV ( vout_thread_t *, picture_t *, picture_t * );
50 static void I422_cyuv ( vout_thread_t *, picture_t *, picture_t * );
51 #if defined (MODULE_NAME_IS_i422_yuy2)
52 static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
53 static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
56 /*****************************************************************************
58 *****************************************************************************/
60 #if defined (MODULE_NAME_IS_i422_yuy2)
61 set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
62 set_capability( "chroma", 80 );
63 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
64 set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
65 set_capability( "chroma", 100 );
66 add_requirement( MMX );
67 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
68 set_description( _("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) );
69 set_capability( "chroma", 120 );
70 add_requirement( SSE2 );
72 set_callbacks( Activate, NULL );
75 /*****************************************************************************
76 * Activate: allocate a chroma function
77 *****************************************************************************
78 * This function allocates and initializes a chroma function
79 *****************************************************************************/
80 static int Activate( vlc_object_t *p_this )
82 vout_thread_t *p_vout = (vout_thread_t *)p_this;
84 if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
89 switch( p_vout->render.i_chroma )
91 case VLC_FOURCC('I','4','2','2'):
92 switch( p_vout->output.i_chroma )
94 case VLC_FOURCC('Y','U','Y','2'):
95 case VLC_FOURCC('Y','U','N','V'):
96 p_vout->chroma.pf_convert = I422_YUY2;
99 case VLC_FOURCC('Y','V','Y','U'):
100 p_vout->chroma.pf_convert = I422_YVYU;
103 case VLC_FOURCC('U','Y','V','Y'):
104 case VLC_FOURCC('U','Y','N','V'):
105 case VLC_FOURCC('Y','4','2','2'):
106 p_vout->chroma.pf_convert = I422_UYVY;
109 case VLC_FOURCC('I','U','Y','V'):
110 p_vout->chroma.pf_convert = I422_IUYV;
113 case VLC_FOURCC('c','y','u','v'):
114 p_vout->chroma.pf_convert = I422_cyuv;
117 #if defined (MODULE_NAME_IS_i422_yuy2)
118 case VLC_FOURCC('Y','2','1','1'):
119 p_vout->chroma.pf_convert = I422_Y211;
134 /* Following functions are local */
136 /*****************************************************************************
137 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
138 *****************************************************************************/
139 static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
142 uint8_t *p_line = p_dest->p->p_pixels;
143 uint8_t *p_y = p_source->Y_PIXELS;
144 uint8_t *p_u = p_source->U_PIXELS;
145 uint8_t *p_v = p_source->V_PIXELS;
149 const int i_source_margin = p_source->p[0].i_pitch
150 - p_source->p[0].i_visible_pitch;
151 const int i_source_margin_c = p_source->p[1].i_pitch
152 - p_source->p[1].i_visible_pitch;
153 const int i_dest_margin = p_dest->p->i_pitch
154 - p_dest->p->i_visible_pitch;
156 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
158 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
159 ((intptr_t)p_line|(intptr_t)p_y))) )
161 /* use faster SSE2 aligned fetch and store */
162 for( i_y = p_vout->render.i_height ; i_y-- ; )
164 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
166 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
168 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
170 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
172 p_y += i_source_margin;
173 p_u += i_source_margin_c;
174 p_v += i_source_margin_c;
175 p_line += i_dest_margin;
179 /* use slower SSE2 unaligned fetch and store */
180 for( i_y = p_vout->render.i_height ; i_y-- ; )
182 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
184 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
186 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
188 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
190 p_y += i_source_margin;
191 p_u += i_source_margin_c;
192 p_v += i_source_margin_c;
193 p_line += i_dest_margin;
200 for( i_y = p_vout->render.i_height ; i_y-- ; )
202 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
204 #if defined (MODULE_NAME_IS_i422_yuy2)
205 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
206 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
207 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
208 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
209 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
210 MMX_CALL( MMX_YUV422_YUYV );
213 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
215 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
217 p_y += i_source_margin;
218 p_u += i_source_margin_c;
219 p_v += i_source_margin_c;
220 p_line += i_dest_margin;
222 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
229 /*****************************************************************************
230 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
231 *****************************************************************************/
232 static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
235 uint8_t *p_line = p_dest->p->p_pixels;
236 uint8_t *p_y = p_source->Y_PIXELS;
237 uint8_t *p_u = p_source->U_PIXELS;
238 uint8_t *p_v = p_source->V_PIXELS;
242 const int i_source_margin = p_source->p[0].i_pitch
243 - p_source->p[0].i_visible_pitch;
244 const int i_source_margin_c = p_source->p[1].i_pitch
245 - p_source->p[1].i_visible_pitch;
246 const int i_dest_margin = p_dest->p->i_pitch
247 - p_dest->p->i_visible_pitch;
249 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
251 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
252 ((intptr_t)p_line|(intptr_t)p_y))) )
254 /* use faster SSE2 aligned fetch and store */
255 for( i_y = p_vout->render.i_height ; i_y-- ; )
257 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
259 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
261 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
263 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
265 p_y += i_source_margin;
266 p_u += i_source_margin_c;
267 p_v += i_source_margin_c;
268 p_line += i_dest_margin;
272 /* use slower SSE2 unaligned fetch and store */
273 for( i_y = p_vout->render.i_height ; i_y-- ; )
275 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
277 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
279 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
281 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
283 p_y += i_source_margin;
284 p_u += i_source_margin_c;
285 p_v += i_source_margin_c;
286 p_line += i_dest_margin;
293 for( i_y = p_vout->render.i_height ; i_y-- ; )
295 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
297 #if defined (MODULE_NAME_IS_i422_yuy2)
298 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
299 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
300 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
301 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
302 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
303 MMX_CALL( MMX_YUV422_YVYU );
306 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
308 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
310 p_y += i_source_margin;
311 p_u += i_source_margin_c;
312 p_v += i_source_margin_c;
313 p_line += i_dest_margin;
315 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
322 /*****************************************************************************
323 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
324 *****************************************************************************/
325 static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
328 uint8_t *p_line = p_dest->p->p_pixels;
329 uint8_t *p_y = p_source->Y_PIXELS;
330 uint8_t *p_u = p_source->U_PIXELS;
331 uint8_t *p_v = p_source->V_PIXELS;
335 const int i_source_margin = p_source->p[0].i_pitch
336 - p_source->p[0].i_visible_pitch;
337 const int i_source_margin_c = p_source->p[1].i_pitch
338 - p_source->p[1].i_visible_pitch;
339 const int i_dest_margin = p_dest->p->i_pitch
340 - p_dest->p->i_visible_pitch;
342 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
344 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
345 ((intptr_t)p_line|(intptr_t)p_y))) )
347 /* use faster SSE2 aligned fetch and store */
348 for( i_y = p_vout->render.i_height ; i_y-- ; )
350 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
352 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
354 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
356 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
358 p_y += i_source_margin;
359 p_u += i_source_margin_c;
360 p_v += i_source_margin_c;
361 p_line += i_dest_margin;
365 /* use slower SSE2 unaligned fetch and store */
366 for( i_y = p_vout->render.i_height ; i_y-- ; )
368 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
370 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
372 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
374 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
376 p_y += i_source_margin;
377 p_u += i_source_margin_c;
378 p_v += i_source_margin_c;
379 p_line += i_dest_margin;
386 for( i_y = p_vout->render.i_height ; i_y-- ; )
388 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
390 #if defined (MODULE_NAME_IS_i422_yuy2)
391 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
392 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
393 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
394 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
395 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
396 MMX_CALL( MMX_YUV422_UYVY );
399 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
401 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
403 p_y += i_source_margin;
404 p_u += i_source_margin_c;
405 p_v += i_source_margin_c;
406 p_line += i_dest_margin;
408 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
415 /*****************************************************************************
416 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
417 *****************************************************************************/
418 static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
422 msg_Err( p_vout, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
425 /*****************************************************************************
426 * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
427 *****************************************************************************/
428 static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
431 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
432 uint8_t *p_y = p_source->Y_PIXELS;
433 uint8_t *p_u = p_source->U_PIXELS;
434 uint8_t *p_v = p_source->V_PIXELS;
438 const int i_source_margin = p_source->p[0].i_pitch
439 - p_source->p[0].i_visible_pitch;
440 const int i_source_margin_c = p_source->p[1].i_pitch
441 - p_source->p[1].i_visible_pitch;
442 const int i_dest_margin = p_dest->p->i_pitch
443 - p_dest->p->i_visible_pitch;
445 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
447 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
448 ((intptr_t)p_line|(intptr_t)p_y))) )
450 /* use faster SSE2 aligned fetch and store */
451 for( i_y = p_vout->render.i_height ; i_y-- ; )
453 p_line -= 2 * p_dest->p->i_pitch;
455 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
457 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
459 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
461 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
463 p_y += i_source_margin;
464 p_u += i_source_margin_c;
465 p_v += i_source_margin_c;
466 p_line += i_dest_margin;
470 /* use slower SSE2 unaligned fetch and store */
471 for( i_y = p_vout->render.i_height ; i_y-- ; )
473 p_line -= 2 * p_dest->p->i_pitch;
475 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
477 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
479 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
481 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
483 p_y += i_source_margin;
484 p_u += i_source_margin_c;
485 p_v += i_source_margin_c;
486 p_line += i_dest_margin;
493 for( i_y = p_vout->render.i_height ; i_y-- ; )
495 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
497 p_line -= 2 * p_dest->p->i_pitch;
499 #if defined (MODULE_NAME_IS_i422_yuy2)
500 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
501 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
502 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
503 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
504 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
505 MMX_CALL( MMX_YUV422_UYVY );
508 p_y += i_source_margin;
509 p_u += i_source_margin_c;
510 p_v += i_source_margin_c;
511 p_line += i_dest_margin;
513 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
515 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
522 /*****************************************************************************
523 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
524 *****************************************************************************/
525 #if defined (MODULE_NAME_IS_i422_yuy2)
526 static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
529 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
530 uint8_t *p_y = p_source->Y_PIXELS;
531 uint8_t *p_u = p_source->U_PIXELS;
532 uint8_t *p_v = p_source->V_PIXELS;
536 for( i_y = p_vout->render.i_height ; i_y-- ; )
538 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
540 C_YUV422_Y211( p_line, p_y, p_u, p_v );
541 C_YUV422_Y211( p_line, p_y, p_u, p_v );