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 *****************************************************************************/
36 #include "i422_yuy2.h"
38 #define SRC_FOURCC "I422"
39 #if defined (MODULE_NAME_IS_i422_yuy2)
40 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
42 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
45 /*****************************************************************************
46 * Local and extern prototypes.
47 *****************************************************************************/
48 static int Activate ( vlc_object_t * );
50 static void I422_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
51 static void I422_YVYU ( vout_thread_t *, picture_t *, picture_t * );
52 static void I422_UYVY ( vout_thread_t *, picture_t *, picture_t * );
53 static void I422_IUYV ( vout_thread_t *, picture_t *, picture_t * );
54 static void I422_cyuv ( vout_thread_t *, picture_t *, picture_t * );
55 #if defined (MODULE_NAME_IS_i422_yuy2)
56 static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
57 static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
60 /*****************************************************************************
62 *****************************************************************************/
64 #if defined (MODULE_NAME_IS_i422_yuy2)
65 set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
66 set_capability( "chroma", 80 );
67 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
68 set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
69 set_capability( "chroma", 100 );
70 add_requirement( MMX );
71 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
72 set_description( _("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) );
73 set_capability( "chroma", 120 );
74 add_requirement( SSE2 );
76 set_callbacks( Activate, NULL );
79 /*****************************************************************************
80 * Activate: allocate a chroma function
81 *****************************************************************************
82 * This function allocates and initializes a chroma function
83 *****************************************************************************/
84 static int Activate( vlc_object_t *p_this )
86 vout_thread_t *p_vout = (vout_thread_t *)p_this;
88 if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
93 switch( p_vout->render.i_chroma )
95 case VLC_FOURCC('I','4','2','2'):
96 switch( p_vout->output.i_chroma )
98 case VLC_FOURCC('Y','U','Y','2'):
99 case VLC_FOURCC('Y','U','N','V'):
100 p_vout->chroma.pf_convert = I422_YUY2;
103 case VLC_FOURCC('Y','V','Y','U'):
104 p_vout->chroma.pf_convert = I422_YVYU;
107 case VLC_FOURCC('U','Y','V','Y'):
108 case VLC_FOURCC('U','Y','N','V'):
109 case VLC_FOURCC('Y','4','2','2'):
110 p_vout->chroma.pf_convert = I422_UYVY;
113 case VLC_FOURCC('I','U','Y','V'):
114 p_vout->chroma.pf_convert = I422_IUYV;
117 case VLC_FOURCC('c','y','u','v'):
118 p_vout->chroma.pf_convert = I422_cyuv;
121 #if defined (MODULE_NAME_IS_i422_yuy2)
122 case VLC_FOURCC('Y','2','1','1'):
123 p_vout->chroma.pf_convert = I422_Y211;
138 /* Following functions are local */
140 /*****************************************************************************
141 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
142 *****************************************************************************/
143 static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
146 uint8_t *p_line = p_dest->p->p_pixels;
147 uint8_t *p_y = p_source->Y_PIXELS;
148 uint8_t *p_u = p_source->U_PIXELS;
149 uint8_t *p_v = p_source->V_PIXELS;
153 const int i_source_margin = p_source->p[0].i_pitch
154 - p_source->p[0].i_visible_pitch;
155 const int i_source_margin_c = p_source->p[1].i_pitch
156 - p_source->p[1].i_visible_pitch;
157 const int i_dest_margin = p_dest->p->i_pitch
158 - p_dest->p->i_visible_pitch;
160 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
162 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
163 ((intptr_t)p_line|(intptr_t)p_y))) )
165 /* use faster SSE2 aligned fetch and store */
166 for( i_y = p_vout->render.i_height ; i_y-- ; )
168 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
170 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
172 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
174 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
176 p_y += i_source_margin;
177 p_u += i_source_margin_c;
178 p_v += i_source_margin_c;
179 p_line += i_dest_margin;
183 /* use slower SSE2 unaligned fetch and store */
184 for( i_y = p_vout->render.i_height ; i_y-- ; )
186 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
188 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
190 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
192 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
194 p_y += i_source_margin;
195 p_u += i_source_margin_c;
196 p_v += i_source_margin_c;
197 p_line += i_dest_margin;
204 for( i_y = p_vout->render.i_height ; i_y-- ; )
206 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
208 #if defined (MODULE_NAME_IS_i422_yuy2)
209 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
210 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
211 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
212 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
213 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
214 MMX_CALL( MMX_YUV422_YUYV );
217 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
219 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
221 p_y += i_source_margin;
222 p_u += i_source_margin_c;
223 p_v += i_source_margin_c;
224 p_line += i_dest_margin;
226 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
233 /*****************************************************************************
234 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
235 *****************************************************************************/
236 static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
239 uint8_t *p_line = p_dest->p->p_pixels;
240 uint8_t *p_y = p_source->Y_PIXELS;
241 uint8_t *p_u = p_source->U_PIXELS;
242 uint8_t *p_v = p_source->V_PIXELS;
246 const int i_source_margin = p_source->p[0].i_pitch
247 - p_source->p[0].i_visible_pitch;
248 const int i_source_margin_c = p_source->p[1].i_pitch
249 - p_source->p[1].i_visible_pitch;
250 const int i_dest_margin = p_dest->p->i_pitch
251 - p_dest->p->i_visible_pitch;
253 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
255 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
256 ((intptr_t)p_line|(intptr_t)p_y))) )
258 /* use faster SSE2 aligned fetch and store */
259 for( i_y = p_vout->render.i_height ; i_y-- ; )
261 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
263 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
265 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
267 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
269 p_y += i_source_margin;
270 p_u += i_source_margin_c;
271 p_v += i_source_margin_c;
272 p_line += i_dest_margin;
276 /* use slower SSE2 unaligned fetch and store */
277 for( i_y = p_vout->render.i_height ; i_y-- ; )
279 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
281 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
283 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
285 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
287 p_y += i_source_margin;
288 p_u += i_source_margin_c;
289 p_v += i_source_margin_c;
290 p_line += i_dest_margin;
297 for( i_y = p_vout->render.i_height ; i_y-- ; )
299 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
301 #if defined (MODULE_NAME_IS_i422_yuy2)
302 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
303 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
304 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
305 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
306 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
307 MMX_CALL( MMX_YUV422_YVYU );
310 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
312 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
314 p_y += i_source_margin;
315 p_u += i_source_margin_c;
316 p_v += i_source_margin_c;
317 p_line += i_dest_margin;
319 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
326 /*****************************************************************************
327 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
328 *****************************************************************************/
329 static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
332 uint8_t *p_line = p_dest->p->p_pixels;
333 uint8_t *p_y = p_source->Y_PIXELS;
334 uint8_t *p_u = p_source->U_PIXELS;
335 uint8_t *p_v = p_source->V_PIXELS;
339 const int i_source_margin = p_source->p[0].i_pitch
340 - p_source->p[0].i_visible_pitch;
341 const int i_source_margin_c = p_source->p[1].i_pitch
342 - p_source->p[1].i_visible_pitch;
343 const int i_dest_margin = p_dest->p->i_pitch
344 - p_dest->p->i_visible_pitch;
346 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
348 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
349 ((intptr_t)p_line|(intptr_t)p_y))) )
351 /* use faster SSE2 aligned fetch and store */
352 for( i_y = p_vout->render.i_height ; i_y-- ; )
354 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
356 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
358 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
360 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
362 p_y += i_source_margin;
363 p_u += i_source_margin_c;
364 p_v += i_source_margin_c;
365 p_line += i_dest_margin;
369 /* use slower SSE2 unaligned fetch and store */
370 for( i_y = p_vout->render.i_height ; i_y-- ; )
372 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
374 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
376 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
378 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
380 p_y += i_source_margin;
381 p_u += i_source_margin_c;
382 p_v += i_source_margin_c;
383 p_line += i_dest_margin;
390 for( i_y = p_vout->render.i_height ; i_y-- ; )
392 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
394 #if defined (MODULE_NAME_IS_i422_yuy2)
395 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
396 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
397 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
398 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
399 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
400 MMX_CALL( MMX_YUV422_UYVY );
403 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
405 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
407 p_y += i_source_margin;
408 p_u += i_source_margin_c;
409 p_v += i_source_margin_c;
410 p_line += i_dest_margin;
412 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
419 /*****************************************************************************
420 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
421 *****************************************************************************/
422 static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
425 VLC_UNUSED(p_source); VLC_UNUSED(p_dest);
427 msg_Err( p_vout, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
430 /*****************************************************************************
431 * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
432 *****************************************************************************/
433 static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
436 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
437 uint8_t *p_y = p_source->Y_PIXELS;
438 uint8_t *p_u = p_source->U_PIXELS;
439 uint8_t *p_v = p_source->V_PIXELS;
443 const int i_source_margin = p_source->p[0].i_pitch
444 - p_source->p[0].i_visible_pitch;
445 const int i_source_margin_c = p_source->p[1].i_pitch
446 - p_source->p[1].i_visible_pitch;
447 const int i_dest_margin = p_dest->p->i_pitch
448 - p_dest->p->i_visible_pitch;
450 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
452 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
453 ((intptr_t)p_line|(intptr_t)p_y))) )
455 /* use faster SSE2 aligned fetch and store */
456 for( i_y = p_vout->render.i_height ; i_y-- ; )
458 p_line -= 2 * p_dest->p->i_pitch;
460 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
462 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
464 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
466 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
468 p_y += i_source_margin;
469 p_u += i_source_margin_c;
470 p_v += i_source_margin_c;
471 p_line += i_dest_margin;
475 /* use slower SSE2 unaligned fetch and store */
476 for( i_y = p_vout->render.i_height ; i_y-- ; )
478 p_line -= 2 * p_dest->p->i_pitch;
480 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
482 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
484 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
486 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
488 p_y += i_source_margin;
489 p_u += i_source_margin_c;
490 p_v += i_source_margin_c;
491 p_line += i_dest_margin;
498 for( i_y = p_vout->render.i_height ; i_y-- ; )
500 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
502 p_line -= 2 * p_dest->p->i_pitch;
504 #if defined (MODULE_NAME_IS_i422_yuy2)
505 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
506 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
507 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
508 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
509 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
510 MMX_CALL( MMX_YUV422_UYVY );
513 p_y += i_source_margin;
514 p_u += i_source_margin_c;
515 p_v += i_source_margin_c;
516 p_line += i_dest_margin;
518 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
520 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
527 /*****************************************************************************
528 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
529 *****************************************************************************/
530 #if defined (MODULE_NAME_IS_i422_yuy2)
531 static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
534 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
535 uint8_t *p_y = p_source->Y_PIXELS;
536 uint8_t *p_u = p_source->U_PIXELS;
537 uint8_t *p_v = p_source->V_PIXELS;
541 for( i_y = p_vout->render.i_height ; i_y-- ; )
543 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
545 C_YUV422_Y211( p_line, p_y, p_u, p_v );
546 C_YUV422_Y211( p_line, p_y, p_u, p_v );