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 *****************************************************************************/
34 #include <vlc_plugin.h>
37 #include "i422_yuy2.h"
39 #define SRC_FOURCC "I422"
40 #if defined (MODULE_NAME_IS_i422_yuy2)
41 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
43 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
46 /*****************************************************************************
47 * Local and extern prototypes.
48 *****************************************************************************/
49 static int Activate ( vlc_object_t * );
51 static void I422_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
52 static void I422_YVYU ( vout_thread_t *, picture_t *, picture_t * );
53 static void I422_UYVY ( vout_thread_t *, picture_t *, picture_t * );
54 static void I422_IUYV ( vout_thread_t *, picture_t *, picture_t * );
55 static void I422_cyuv ( vout_thread_t *, picture_t *, picture_t * );
56 #if defined (MODULE_NAME_IS_i422_yuy2)
57 static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
58 static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
61 /*****************************************************************************
63 *****************************************************************************/
65 #if defined (MODULE_NAME_IS_i422_yuy2)
66 set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
67 set_capability( "chroma", 80 );
68 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
69 set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
70 set_capability( "chroma", 100 );
71 add_requirement( MMX );
72 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
73 set_description( _("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) );
74 set_capability( "chroma", 120 );
75 add_requirement( SSE2 );
77 set_callbacks( Activate, NULL );
80 /*****************************************************************************
81 * Activate: allocate a chroma function
82 *****************************************************************************
83 * This function allocates and initializes a chroma function
84 *****************************************************************************/
85 static int Activate( vlc_object_t *p_this )
87 vout_thread_t *p_vout = (vout_thread_t *)p_this;
89 if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
94 switch( p_vout->render.i_chroma )
96 case VLC_FOURCC('I','4','2','2'):
97 switch( p_vout->output.i_chroma )
99 case VLC_FOURCC('Y','U','Y','2'):
100 case VLC_FOURCC('Y','U','N','V'):
101 p_vout->chroma.pf_convert = I422_YUY2;
104 case VLC_FOURCC('Y','V','Y','U'):
105 p_vout->chroma.pf_convert = I422_YVYU;
108 case VLC_FOURCC('U','Y','V','Y'):
109 case VLC_FOURCC('U','Y','N','V'):
110 case VLC_FOURCC('Y','4','2','2'):
111 p_vout->chroma.pf_convert = I422_UYVY;
114 case VLC_FOURCC('I','U','Y','V'):
115 p_vout->chroma.pf_convert = I422_IUYV;
118 case VLC_FOURCC('c','y','u','v'):
119 p_vout->chroma.pf_convert = I422_cyuv;
122 #if defined (MODULE_NAME_IS_i422_yuy2)
123 case VLC_FOURCC('Y','2','1','1'):
124 p_vout->chroma.pf_convert = I422_Y211;
139 /* Following functions are local */
141 /*****************************************************************************
142 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
143 *****************************************************************************/
144 static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
147 uint8_t *p_line = p_dest->p->p_pixels;
148 uint8_t *p_y = p_source->Y_PIXELS;
149 uint8_t *p_u = p_source->U_PIXELS;
150 uint8_t *p_v = p_source->V_PIXELS;
154 const int i_source_margin = p_source->p[0].i_pitch
155 - p_source->p[0].i_visible_pitch;
156 const int i_source_margin_c = p_source->p[1].i_pitch
157 - p_source->p[1].i_visible_pitch;
158 const int i_dest_margin = p_dest->p->i_pitch
159 - p_dest->p->i_visible_pitch;
161 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
163 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
164 ((intptr_t)p_line|(intptr_t)p_y))) )
166 /* use faster SSE2 aligned fetch and store */
167 for( i_y = p_vout->render.i_height ; i_y-- ; )
169 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
171 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
173 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
175 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
177 p_y += i_source_margin;
178 p_u += i_source_margin_c;
179 p_v += i_source_margin_c;
180 p_line += i_dest_margin;
184 /* use slower SSE2 unaligned fetch and store */
185 for( i_y = p_vout->render.i_height ; i_y-- ; )
187 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
189 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
191 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
193 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
195 p_y += i_source_margin;
196 p_u += i_source_margin_c;
197 p_v += i_source_margin_c;
198 p_line += i_dest_margin;
205 for( i_y = p_vout->render.i_height ; i_y-- ; )
207 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
209 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
214 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
215 MMX_CALL( MMX_YUV422_YUYV );
218 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
220 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
222 p_y += i_source_margin;
223 p_u += i_source_margin_c;
224 p_v += i_source_margin_c;
225 p_line += i_dest_margin;
227 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
234 /*****************************************************************************
235 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
236 *****************************************************************************/
237 static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
240 uint8_t *p_line = p_dest->p->p_pixels;
241 uint8_t *p_y = p_source->Y_PIXELS;
242 uint8_t *p_u = p_source->U_PIXELS;
243 uint8_t *p_v = p_source->V_PIXELS;
247 const int i_source_margin = p_source->p[0].i_pitch
248 - p_source->p[0].i_visible_pitch;
249 const int i_source_margin_c = p_source->p[1].i_pitch
250 - p_source->p[1].i_visible_pitch;
251 const int i_dest_margin = p_dest->p->i_pitch
252 - p_dest->p->i_visible_pitch;
254 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
256 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
257 ((intptr_t)p_line|(intptr_t)p_y))) )
259 /* use faster SSE2 aligned fetch and store */
260 for( i_y = p_vout->render.i_height ; i_y-- ; )
262 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
264 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
266 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
268 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
270 p_y += i_source_margin;
271 p_u += i_source_margin_c;
272 p_v += i_source_margin_c;
273 p_line += i_dest_margin;
277 /* use slower SSE2 unaligned fetch and store */
278 for( i_y = p_vout->render.i_height ; i_y-- ; )
280 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
282 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
284 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
286 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
288 p_y += i_source_margin;
289 p_u += i_source_margin_c;
290 p_v += i_source_margin_c;
291 p_line += i_dest_margin;
298 for( i_y = p_vout->render.i_height ; i_y-- ; )
300 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
302 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
307 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
308 MMX_CALL( MMX_YUV422_YVYU );
311 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
313 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
315 p_y += i_source_margin;
316 p_u += i_source_margin_c;
317 p_v += i_source_margin_c;
318 p_line += i_dest_margin;
320 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
327 /*****************************************************************************
328 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
329 *****************************************************************************/
330 static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
333 uint8_t *p_line = p_dest->p->p_pixels;
334 uint8_t *p_y = p_source->Y_PIXELS;
335 uint8_t *p_u = p_source->U_PIXELS;
336 uint8_t *p_v = p_source->V_PIXELS;
340 const int i_source_margin = p_source->p[0].i_pitch
341 - p_source->p[0].i_visible_pitch;
342 const int i_source_margin_c = p_source->p[1].i_pitch
343 - p_source->p[1].i_visible_pitch;
344 const int i_dest_margin = p_dest->p->i_pitch
345 - p_dest->p->i_visible_pitch;
347 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
349 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
350 ((intptr_t)p_line|(intptr_t)p_y))) )
352 /* use faster SSE2 aligned fetch and store */
353 for( i_y = p_vout->render.i_height ; i_y-- ; )
355 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
357 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
359 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
361 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
363 p_y += i_source_margin;
364 p_u += i_source_margin_c;
365 p_v += i_source_margin_c;
366 p_line += i_dest_margin;
370 /* use slower SSE2 unaligned fetch and store */
371 for( i_y = p_vout->render.i_height ; i_y-- ; )
373 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
375 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
377 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
379 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
381 p_y += i_source_margin;
382 p_u += i_source_margin_c;
383 p_v += i_source_margin_c;
384 p_line += i_dest_margin;
391 for( i_y = p_vout->render.i_height ; i_y-- ; )
393 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
395 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
400 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
401 MMX_CALL( MMX_YUV422_UYVY );
404 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
406 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
408 p_y += i_source_margin;
409 p_u += i_source_margin_c;
410 p_v += i_source_margin_c;
411 p_line += i_dest_margin;
413 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
420 /*****************************************************************************
421 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
422 *****************************************************************************/
423 static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
426 VLC_UNUSED(p_source); VLC_UNUSED(p_dest);
428 msg_Err( p_vout, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
431 /*****************************************************************************
432 * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
433 *****************************************************************************/
434 static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
437 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
438 uint8_t *p_y = p_source->Y_PIXELS;
439 uint8_t *p_u = p_source->U_PIXELS;
440 uint8_t *p_v = p_source->V_PIXELS;
444 const int i_source_margin = p_source->p[0].i_pitch
445 - p_source->p[0].i_visible_pitch;
446 const int i_source_margin_c = p_source->p[1].i_pitch
447 - p_source->p[1].i_visible_pitch;
448 const int i_dest_margin = p_dest->p->i_pitch
449 - p_dest->p->i_visible_pitch;
451 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
453 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
454 ((intptr_t)p_line|(intptr_t)p_y))) )
456 /* use faster SSE2 aligned fetch and store */
457 for( i_y = p_vout->render.i_height ; i_y-- ; )
459 p_line -= 2 * p_dest->p->i_pitch;
461 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
463 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
465 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
467 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
469 p_y += i_source_margin;
470 p_u += i_source_margin_c;
471 p_v += i_source_margin_c;
472 p_line += i_dest_margin;
476 /* use slower SSE2 unaligned fetch and store */
477 for( i_y = p_vout->render.i_height ; i_y-- ; )
479 p_line -= 2 * p_dest->p->i_pitch;
481 for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
483 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
485 for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
487 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
489 p_y += i_source_margin;
490 p_u += i_source_margin_c;
491 p_v += i_source_margin_c;
492 p_line += i_dest_margin;
499 for( i_y = p_vout->render.i_height ; i_y-- ; )
501 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
503 p_line -= 2 * p_dest->p->i_pitch;
505 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
510 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
511 MMX_CALL( MMX_YUV422_UYVY );
514 p_y += i_source_margin;
515 p_u += i_source_margin_c;
516 p_v += i_source_margin_c;
517 p_line += i_dest_margin;
519 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
521 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
528 /*****************************************************************************
529 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
530 *****************************************************************************/
531 #if defined (MODULE_NAME_IS_i422_yuy2)
532 static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
535 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
536 uint8_t *p_y = p_source->Y_PIXELS;
537 uint8_t *p_u = p_source->U_PIXELS;
538 uint8_t *p_v = p_source->V_PIXELS;
542 for( i_y = p_vout->render.i_height ; i_y-- ; )
544 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
546 C_YUV422_Y211( p_line, p_y, p_u, p_v );
547 C_YUV422_Y211( p_line, p_y, p_u, p_v );