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 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_filter.h>
38 #include "i422_yuy2.h"
40 #define SRC_FOURCC "I422"
41 #if defined (MODULE_NAME_IS_i422_yuy2)
42 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
44 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
47 /*****************************************************************************
48 * Local and extern prototypes.
49 *****************************************************************************/
50 static int Activate ( vlc_object_t * );
52 static void I422_YUY2 ( filter_t *, picture_t *, picture_t * );
53 static void I422_YVYU ( filter_t *, picture_t *, picture_t * );
54 static void I422_UYVY ( filter_t *, picture_t *, picture_t * );
55 static void I422_IUYV ( filter_t *, picture_t *, picture_t * );
56 static void I422_cyuv ( filter_t *, picture_t *, picture_t * );
57 static picture_t *I422_YUY2_Filter ( filter_t *, picture_t * );
58 static picture_t *I422_YVYU_Filter ( filter_t *, picture_t * );
59 static picture_t *I422_UYVY_Filter ( filter_t *, picture_t * );
60 static picture_t *I422_IUYV_Filter ( filter_t *, picture_t * );
61 static picture_t *I422_cyuv_Filter ( filter_t *, picture_t * );
62 #if defined (MODULE_NAME_IS_i422_yuy2)
63 static void I422_Y211 ( filter_t *, picture_t *, picture_t * );
64 static picture_t *I422_Y211_Filter ( filter_t *, picture_t * );
67 /*****************************************************************************
69 *****************************************************************************/
71 #if defined (MODULE_NAME_IS_i422_yuy2)
72 set_description( N_("Conversions from " SRC_FOURCC " to " DEST_FOURCC) )
73 set_capability( "video filter2", 80 )
74 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
75 set_description( N_("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) )
76 set_capability( "video filter2", 100 )
77 add_requirement( MMX )
78 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
79 set_description( N_("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) )
80 set_capability( "video filter2", 120 )
81 add_requirement( SSE2 )
83 set_callbacks( Activate, NULL )
86 /*****************************************************************************
87 * Activate: allocate a chroma function
88 *****************************************************************************
89 * This function allocates and initializes a chroma function
90 *****************************************************************************/
91 static int Activate( vlc_object_t *p_this )
93 filter_t *p_filter = (filter_t *)p_this;
95 if( p_filter->fmt_in.video.i_width & 1
96 || p_filter->fmt_in.video.i_height & 1 )
101 switch( p_filter->fmt_in.video.i_chroma )
103 case VLC_FOURCC('I','4','2','2'):
104 switch( p_filter->fmt_out.video.i_chroma )
106 case VLC_FOURCC('Y','U','Y','2'):
107 case VLC_FOURCC('Y','U','N','V'):
108 p_filter->pf_video_filter = I422_YUY2_Filter;
111 case VLC_FOURCC('Y','V','Y','U'):
112 p_filter->pf_video_filter = I422_YVYU_Filter;
115 case VLC_FOURCC('U','Y','V','Y'):
116 case VLC_FOURCC('U','Y','N','V'):
117 case VLC_FOURCC('Y','4','2','2'):
118 p_filter->pf_video_filter = I422_UYVY_Filter;
121 case VLC_FOURCC('I','U','Y','V'):
122 p_filter->pf_video_filter = I422_IUYV_Filter;
125 case VLC_FOURCC('c','y','u','v'):
126 p_filter->pf_video_filter = I422_cyuv_Filter;
129 #if defined (MODULE_NAME_IS_i422_yuy2)
130 case VLC_FOURCC('Y','2','1','1'):
131 p_filter->pf_video_filter = I422_Y211_Filter;
146 /* Following functions are local */
148 VIDEO_FILTER_WRAPPER( I422_YUY2 )
149 VIDEO_FILTER_WRAPPER( I422_YVYU )
150 VIDEO_FILTER_WRAPPER( I422_UYVY )
151 VIDEO_FILTER_WRAPPER( I422_IUYV )
152 VIDEO_FILTER_WRAPPER( I422_cyuv )
153 #if defined (MODULE_NAME_IS_i422_yuy2)
154 VIDEO_FILTER_WRAPPER( I422_Y211 )
157 /*****************************************************************************
158 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
159 *****************************************************************************/
160 static void I422_YUY2( filter_t *p_filter, picture_t *p_source,
163 uint8_t *p_line = p_dest->p->p_pixels;
164 uint8_t *p_y = p_source->Y_PIXELS;
165 uint8_t *p_u = p_source->U_PIXELS;
166 uint8_t *p_v = p_source->V_PIXELS;
170 const int i_source_margin = p_source->p[0].i_pitch
171 - p_source->p[0].i_visible_pitch;
172 const int i_source_margin_c = p_source->p[1].i_pitch
173 - p_source->p[1].i_visible_pitch;
174 const int i_dest_margin = p_dest->p->i_pitch
175 - p_dest->p->i_visible_pitch;
177 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
179 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
180 ((intptr_t)p_line|(intptr_t)p_y))) )
182 /* use faster SSE2 aligned fetch and store */
183 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
185 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
187 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
189 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
191 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
193 p_y += i_source_margin;
194 p_u += i_source_margin_c;
195 p_v += i_source_margin_c;
196 p_line += i_dest_margin;
200 /* use slower SSE2 unaligned fetch and store */
201 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
203 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
205 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
207 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
209 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
211 p_y += i_source_margin;
212 p_u += i_source_margin_c;
213 p_v += i_source_margin_c;
214 p_line += i_dest_margin;
221 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
223 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
225 #if defined (MODULE_NAME_IS_i422_yuy2)
226 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
227 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
228 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
229 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
230 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
231 MMX_CALL( MMX_YUV422_YUYV );
234 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
236 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
238 p_y += i_source_margin;
239 p_u += i_source_margin_c;
240 p_v += i_source_margin_c;
241 p_line += i_dest_margin;
243 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
250 /*****************************************************************************
251 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
252 *****************************************************************************/
253 static void I422_YVYU( filter_t *p_filter, picture_t *p_source,
256 uint8_t *p_line = p_dest->p->p_pixels;
257 uint8_t *p_y = p_source->Y_PIXELS;
258 uint8_t *p_u = p_source->U_PIXELS;
259 uint8_t *p_v = p_source->V_PIXELS;
263 const int i_source_margin = p_source->p[0].i_pitch
264 - p_source->p[0].i_visible_pitch;
265 const int i_source_margin_c = p_source->p[1].i_pitch
266 - p_source->p[1].i_visible_pitch;
267 const int i_dest_margin = p_dest->p->i_pitch
268 - p_dest->p->i_visible_pitch;
270 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
272 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
273 ((intptr_t)p_line|(intptr_t)p_y))) )
275 /* use faster SSE2 aligned fetch and store */
276 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
278 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
280 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
282 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
284 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
286 p_y += i_source_margin;
287 p_u += i_source_margin_c;
288 p_v += i_source_margin_c;
289 p_line += i_dest_margin;
293 /* use slower SSE2 unaligned fetch and store */
294 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
296 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
298 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
300 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
302 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
304 p_y += i_source_margin;
305 p_u += i_source_margin_c;
306 p_v += i_source_margin_c;
307 p_line += i_dest_margin;
314 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
316 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
318 #if defined (MODULE_NAME_IS_i422_yuy2)
319 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
320 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
321 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
322 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
323 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
324 MMX_CALL( MMX_YUV422_YVYU );
327 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
329 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
331 p_y += i_source_margin;
332 p_u += i_source_margin_c;
333 p_v += i_source_margin_c;
334 p_line += i_dest_margin;
336 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
343 /*****************************************************************************
344 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
345 *****************************************************************************/
346 static void I422_UYVY( filter_t *p_filter, picture_t *p_source,
349 uint8_t *p_line = p_dest->p->p_pixels;
350 uint8_t *p_y = p_source->Y_PIXELS;
351 uint8_t *p_u = p_source->U_PIXELS;
352 uint8_t *p_v = p_source->V_PIXELS;
356 const int i_source_margin = p_source->p[0].i_pitch
357 - p_source->p[0].i_visible_pitch;
358 const int i_source_margin_c = p_source->p[1].i_pitch
359 - p_source->p[1].i_visible_pitch;
360 const int i_dest_margin = p_dest->p->i_pitch
361 - p_dest->p->i_visible_pitch;
363 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
365 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
366 ((intptr_t)p_line|(intptr_t)p_y))) )
368 /* use faster SSE2 aligned fetch and store */
369 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
371 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
373 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
375 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
377 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
379 p_y += i_source_margin;
380 p_u += i_source_margin_c;
381 p_v += i_source_margin_c;
382 p_line += i_dest_margin;
386 /* use slower SSE2 unaligned fetch and store */
387 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
389 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
391 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
393 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
395 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
397 p_y += i_source_margin;
398 p_u += i_source_margin_c;
399 p_v += i_source_margin_c;
400 p_line += i_dest_margin;
407 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
409 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
411 #if defined (MODULE_NAME_IS_i422_yuy2)
412 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
413 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
414 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
415 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
416 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
417 MMX_CALL( MMX_YUV422_UYVY );
420 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
422 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
424 p_y += i_source_margin;
425 p_u += i_source_margin_c;
426 p_v += i_source_margin_c;
427 p_line += i_dest_margin;
429 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
436 /*****************************************************************************
437 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
438 *****************************************************************************/
439 static void I422_IUYV( filter_t *p_filter, picture_t *p_source,
442 VLC_UNUSED(p_source); VLC_UNUSED(p_dest);
444 msg_Err( p_filter, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
447 /*****************************************************************************
448 * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
449 *****************************************************************************/
450 static void I422_cyuv( filter_t *p_filter, picture_t *p_source,
453 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
454 uint8_t *p_y = p_source->Y_PIXELS;
455 uint8_t *p_u = p_source->U_PIXELS;
456 uint8_t *p_v = p_source->V_PIXELS;
460 const int i_source_margin = p_source->p[0].i_pitch
461 - p_source->p[0].i_visible_pitch;
462 const int i_source_margin_c = p_source->p[1].i_pitch
463 - p_source->p[1].i_visible_pitch;
464 const int i_dest_margin = p_dest->p->i_pitch
465 - p_dest->p->i_visible_pitch;
467 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
469 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
470 ((intptr_t)p_line|(intptr_t)p_y))) )
472 /* use faster SSE2 aligned fetch and store */
473 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
475 p_line -= 2 * p_dest->p->i_pitch;
477 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
479 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
481 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
483 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
485 p_y += i_source_margin;
486 p_u += i_source_margin_c;
487 p_v += i_source_margin_c;
488 p_line += i_dest_margin;
492 /* use slower SSE2 unaligned fetch and store */
493 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
495 p_line -= 2 * p_dest->p->i_pitch;
497 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
499 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
501 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
503 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
505 p_y += i_source_margin;
506 p_u += i_source_margin_c;
507 p_v += i_source_margin_c;
508 p_line += i_dest_margin;
515 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
517 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
519 p_line -= 2 * p_dest->p->i_pitch;
521 #if defined (MODULE_NAME_IS_i422_yuy2)
522 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
523 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
524 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
525 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
526 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
527 MMX_CALL( MMX_YUV422_UYVY );
530 p_y += i_source_margin;
531 p_u += i_source_margin_c;
532 p_v += i_source_margin_c;
533 p_line += i_dest_margin;
535 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
537 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
544 /*****************************************************************************
545 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
546 *****************************************************************************/
547 #if defined (MODULE_NAME_IS_i422_yuy2)
548 static void I422_Y211( filter_t *p_filter, picture_t *p_source,
551 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
552 uint8_t *p_y = p_source->Y_PIXELS;
553 uint8_t *p_u = p_source->U_PIXELS;
554 uint8_t *p_v = p_source->V_PIXELS;
558 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
560 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
562 C_YUV422_Y211( p_line, p_y, p_u, p_v );
563 C_YUV422_Y211( p_line, p_y, p_u, p_v );