1 /*****************************************************************************
2 * i422_yuy2.c : Planar YUV 4:2:2 to Packed YUV conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VLC authors and VideoLAN
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 it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * 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 # define vlc_CPU_capable() (true)
76 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
77 set_description( N_("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) )
78 set_capability( "video filter2", 100 )
79 # define vlc_CPU_capable() vlc_CPU_MMX()
80 # define VLC_TARGET VLC_MMX
81 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
82 set_description( N_("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) )
83 set_capability( "video filter2", 120 )
84 # define vlc_CPU_capable() vlc_CPU_SSE2()
85 # define VLC_TARGET VLC_SSE
87 set_callbacks( Activate, NULL )
90 /*****************************************************************************
91 * Activate: allocate a chroma function
92 *****************************************************************************
93 * This function allocates and initializes a chroma function
94 *****************************************************************************/
95 static int Activate( vlc_object_t *p_this )
97 filter_t *p_filter = (filter_t *)p_this;
99 if( !vlc_CPU_capable() )
101 if( p_filter->fmt_in.video.i_width & 1
102 || p_filter->fmt_in.video.i_height & 1 )
107 if( p_filter->fmt_in.video.orientation != p_filter->fmt_out.video.orientation )
112 switch( p_filter->fmt_in.video.i_chroma )
115 switch( p_filter->fmt_out.video.i_chroma )
118 p_filter->pf_video_filter = I422_YUY2_Filter;
122 p_filter->pf_video_filter = I422_YVYU_Filter;
126 p_filter->pf_video_filter = I422_UYVY_Filter;
129 case VLC_FOURCC('I','U','Y','V'):
130 p_filter->pf_video_filter = I422_IUYV_Filter;
134 p_filter->pf_video_filter = I422_cyuv_Filter;
137 #if defined (MODULE_NAME_IS_i422_yuy2)
139 p_filter->pf_video_filter = I422_Y211_Filter;
154 /* Following functions are local */
156 VIDEO_FILTER_WRAPPER( I422_YUY2 )
157 VIDEO_FILTER_WRAPPER( I422_YVYU )
158 VIDEO_FILTER_WRAPPER( I422_UYVY )
159 VIDEO_FILTER_WRAPPER( I422_IUYV )
160 VIDEO_FILTER_WRAPPER( I422_cyuv )
161 #if defined (MODULE_NAME_IS_i422_yuy2)
162 VIDEO_FILTER_WRAPPER( I422_Y211 )
165 /*****************************************************************************
166 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
167 *****************************************************************************/
169 static void I422_YUY2( filter_t *p_filter, picture_t *p_source,
172 uint8_t *p_line = p_dest->p->p_pixels;
173 uint8_t *p_y = p_source->Y_PIXELS;
174 uint8_t *p_u = p_source->U_PIXELS;
175 uint8_t *p_v = p_source->V_PIXELS;
179 const int i_source_margin = p_source->p[0].i_pitch
180 - p_source->p[0].i_visible_pitch;
181 const int i_source_margin_c = p_source->p[1].i_pitch
182 - p_source->p[1].i_visible_pitch;
183 const int i_dest_margin = p_dest->p->i_pitch
184 - p_dest->p->i_visible_pitch;
186 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
188 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
189 ((intptr_t)p_line|(intptr_t)p_y))) )
191 /* use faster SSE2 aligned fetch and store */
192 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
194 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
196 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
198 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
200 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
202 p_y += i_source_margin;
203 p_u += i_source_margin_c;
204 p_v += i_source_margin_c;
205 p_line += i_dest_margin;
209 /* use slower SSE2 unaligned fetch and store */
210 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
212 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
214 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
216 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
218 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
220 p_y += i_source_margin;
221 p_u += i_source_margin_c;
222 p_v += i_source_margin_c;
223 p_line += i_dest_margin;
230 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
232 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
234 #if defined (MODULE_NAME_IS_i422_yuy2)
235 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
236 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
237 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
238 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
239 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
240 MMX_CALL( MMX_YUV422_YUYV );
243 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
245 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
247 p_y += i_source_margin;
248 p_u += i_source_margin_c;
249 p_v += i_source_margin_c;
250 p_line += i_dest_margin;
252 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
259 /*****************************************************************************
260 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
261 *****************************************************************************/
263 static void I422_YVYU( filter_t *p_filter, picture_t *p_source,
266 uint8_t *p_line = p_dest->p->p_pixels;
267 uint8_t *p_y = p_source->Y_PIXELS;
268 uint8_t *p_u = p_source->U_PIXELS;
269 uint8_t *p_v = p_source->V_PIXELS;
273 const int i_source_margin = p_source->p[0].i_pitch
274 - p_source->p[0].i_visible_pitch;
275 const int i_source_margin_c = p_source->p[1].i_pitch
276 - p_source->p[1].i_visible_pitch;
277 const int i_dest_margin = p_dest->p->i_pitch
278 - p_dest->p->i_visible_pitch;
280 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
282 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
283 ((intptr_t)p_line|(intptr_t)p_y))) )
285 /* use faster SSE2 aligned fetch and store */
286 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
288 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
290 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
292 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
294 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
296 p_y += i_source_margin;
297 p_u += i_source_margin_c;
298 p_v += i_source_margin_c;
299 p_line += i_dest_margin;
303 /* use slower SSE2 unaligned fetch and store */
304 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
306 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
308 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
310 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 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;
324 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
326 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
328 #if defined (MODULE_NAME_IS_i422_yuy2)
329 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
330 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
331 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
332 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
333 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
334 MMX_CALL( MMX_YUV422_YVYU );
337 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
339 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
341 p_y += i_source_margin;
342 p_u += i_source_margin_c;
343 p_v += i_source_margin_c;
344 p_line += i_dest_margin;
346 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
353 /*****************************************************************************
354 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
355 *****************************************************************************/
357 static void I422_UYVY( filter_t *p_filter, picture_t *p_source,
360 uint8_t *p_line = p_dest->p->p_pixels;
361 uint8_t *p_y = p_source->Y_PIXELS;
362 uint8_t *p_u = p_source->U_PIXELS;
363 uint8_t *p_v = p_source->V_PIXELS;
367 const int i_source_margin = p_source->p[0].i_pitch
368 - p_source->p[0].i_visible_pitch;
369 const int i_source_margin_c = p_source->p[1].i_pitch
370 - p_source->p[1].i_visible_pitch;
371 const int i_dest_margin = p_dest->p->i_pitch
372 - p_dest->p->i_visible_pitch;
374 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
376 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
377 ((intptr_t)p_line|(intptr_t)p_y))) )
379 /* use faster SSE2 aligned fetch and store */
380 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
382 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
384 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
386 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
388 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
390 p_y += i_source_margin;
391 p_u += i_source_margin_c;
392 p_v += i_source_margin_c;
393 p_line += i_dest_margin;
397 /* use slower SSE2 unaligned fetch and store */
398 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
400 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
402 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
404 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 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;
418 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
420 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
422 #if defined (MODULE_NAME_IS_i422_yuy2)
423 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
424 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
425 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
426 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
427 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
428 MMX_CALL( MMX_YUV422_UYVY );
431 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
433 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
435 p_y += i_source_margin;
436 p_u += i_source_margin_c;
437 p_v += i_source_margin_c;
438 p_line += i_dest_margin;
440 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
447 /*****************************************************************************
448 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
449 *****************************************************************************/
450 static void I422_IUYV( filter_t *p_filter, picture_t *p_source,
453 VLC_UNUSED(p_source); VLC_UNUSED(p_dest);
455 msg_Err( p_filter, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
458 /*****************************************************************************
459 * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
460 *****************************************************************************/
462 static void I422_cyuv( filter_t *p_filter, picture_t *p_source,
465 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
466 uint8_t *p_y = p_source->Y_PIXELS;
467 uint8_t *p_u = p_source->U_PIXELS;
468 uint8_t *p_v = p_source->V_PIXELS;
472 const int i_source_margin = p_source->p[0].i_pitch
473 - p_source->p[0].i_visible_pitch;
474 const int i_source_margin_c = p_source->p[1].i_pitch
475 - p_source->p[1].i_visible_pitch;
476 const int i_dest_margin = p_dest->p->i_pitch
477 - p_dest->p->i_visible_pitch;
479 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
481 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
482 ((intptr_t)p_line|(intptr_t)p_y))) )
484 /* use faster SSE2 aligned fetch and store */
485 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
487 p_line -= 2 * p_dest->p->i_pitch;
489 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
491 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
493 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
495 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
497 p_y += i_source_margin;
498 p_u += i_source_margin_c;
499 p_v += i_source_margin_c;
500 p_line += i_dest_margin;
504 /* use slower SSE2 unaligned fetch and store */
505 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
507 p_line -= 2 * p_dest->p->i_pitch;
509 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
511 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
513 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
515 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
517 p_y += i_source_margin;
518 p_u += i_source_margin_c;
519 p_v += i_source_margin_c;
520 p_line += i_dest_margin;
527 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
529 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
531 p_line -= 2 * p_dest->p->i_pitch;
533 #if defined (MODULE_NAME_IS_i422_yuy2)
534 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
535 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
536 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
537 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
538 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
539 MMX_CALL( MMX_YUV422_UYVY );
542 p_y += i_source_margin;
543 p_u += i_source_margin_c;
544 p_v += i_source_margin_c;
545 p_line += i_dest_margin;
547 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
549 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
556 /*****************************************************************************
557 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
558 *****************************************************************************/
559 #if defined (MODULE_NAME_IS_i422_yuy2)
560 static void I422_Y211( filter_t *p_filter, picture_t *p_source,
563 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
564 uint8_t *p_y = p_source->Y_PIXELS;
565 uint8_t *p_u = p_source->U_PIXELS;
566 uint8_t *p_v = p_source->V_PIXELS;
570 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
572 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
574 C_YUV422_Y211( p_line, p_y, p_u, p_v );
575 C_YUV422_Y211( p_line, p_y, p_u, p_v );